twz_rt/
syms.rs

1#![allow(unused_variables)]
2#![allow(non_snake_case)]
3#![allow(improper_ctypes_definitions)]
4
5// This macro checks that our definition of a function is the same as that
6// defined by the bindings generated from bindgen. Thus the whole ABI
7// is type-checked! The only trick is that you have to specify the number of arguments.
8macro_rules! check_ffi_type {
9    ($f1:ident) => {
10        paste::paste! {
11            #[allow(dead_code, unused_variables, unused_assignments)]
12            fn [<__tc_ffi_ $f1>]() {
13                let mut x: unsafe extern "C-unwind" fn() -> _ = $f1;
14                x = twizzler_rt_abi::bindings::$f1;
15            }
16        }
17    };
18    ($f1:ident, _) => {
19        paste::paste! {
20            #[allow(dead_code, unused_variables, unused_assignments)]
21            fn [<__tc_ffi_ $f1>]() {
22                let mut x: unsafe extern "C-unwind" fn(_) -> _ = $f1;
23                x = twizzler_rt_abi::bindings::$f1;
24            }
25        }
26    };
27    ($f1:ident, _, _) => {
28        paste::paste! {
29            #[allow(dead_code, unused_variables, unused_assignments)]
30            fn [<__tc_ffi_ $f1>]() {
31                let mut x: unsafe extern "C-unwind" fn(_, _) -> _ = $f1;
32                x = twizzler_rt_abi::bindings::$f1;
33            }
34        }
35    };
36    ($f1:ident, _, _, _) => {
37        paste::paste! {
38            #[allow(dead_code, unused_variables, unused_assignments)]
39            fn [<__tc_ffi_ $f1>]() {
40                let mut x: unsafe extern "C-unwind" fn(_, _, _) -> _ = $f1;
41                x = twizzler_rt_abi::bindings::$f1;
42            }
43        }
44    };
45    ($f1:ident, _, _, _, _) => {
46        paste::paste! {
47            #[allow(dead_code, unused_variables, unused_assignments)]
48            fn [<__tc_ffi_ $f1>]() {
49                let mut x: unsafe extern "C-unwind" fn(_, _, _, _) -> _ = $f1;
50                x = twizzler_rt_abi::bindings::$f1;
51            }
52        }
53    };
54    ($f1:ident, _, _, _, _, _) => {
55        paste::paste! {
56            #[allow(dead_code, unused_variables, unused_assignments)]
57            fn [<__tc_ffi_ $f1>]() {
58                let mut x: unsafe extern "C-unwind" fn(_, _, _, _, _) -> _ = $f1;
59                x = twizzler_rt_abi::bindings::$f1;
60            }
61        }
62    };
63    ($f1:ident, _, _, _, _, _, _) => {
64        paste::paste! {
65            #[allow(dead_code, unused_variables, unused_assignments)]
66            fn [<__tc_ffi_ $f1>]() {
67                let mut x: unsafe extern "C-unwind" fn(_, _, _, _, _, _) -> _ = $f1;
68                x = twizzler_rt_abi::bindings::$f1;
69            }
70        }
71    };
72    ($f1:ident, _, _, _, _, _, _, _) => {
73        paste::paste! {
74            #[allow(dead_code, unused_variables, unused_assignments)]
75            fn [<__tc_ffi_ $f1>]() {
76                let mut x: unsafe extern "C-unwind" fn(_, _, _, _, _, _, _) -> _ = $f1;
77                x = twizzler_rt_abi::bindings::$f1;
78            }
79        }
80    };
81}
82
83use std::{
84    alloc::GlobalAlloc,
85    ffi::{c_void, CStr},
86};
87
88use tracing::warn;
89use twizzler_abi::{
90    object::{ObjID, MAX_SIZE},
91    syscall::ObjectCreate,
92};
93// core.h
94use twizzler_rt_abi::bindings::{
95    binding_info, endpoint, fd_set, io_ctx, name_resolver, name_root, object_cmd, object_create,
96    object_source, object_tie, option_exit_code, release_flags, twz_error, u32_result, wait_kind,
97};
98use twizzler_rt_abi::error::{ArgumentError, RawTwzError, TwzError};
99
100use crate::{runtime::OUR_RUNTIME, set_upcall_handler};
101
102#[no_mangle]
103pub unsafe extern "C-unwind" fn twz_rt_abort() {
104    OUR_RUNTIME.abort();
105}
106check_ffi_type!(twz_rt_abort);
107
108#[no_mangle]
109pub unsafe extern "C-unwind" fn twz_rt_exit(code: i32) {
110    OUR_RUNTIME.exit(code);
111}
112check_ffi_type!(twz_rt_exit, _);
113
114#[no_mangle]
115pub unsafe extern "C-unwind" fn twz_rt_pre_main_hook() -> option_exit_code {
116    match OUR_RUNTIME.pre_main_hook() {
117        Some(ec) => option_exit_code {
118            is_some: 1,
119            value: ec,
120        },
121        None => option_exit_code {
122            is_some: 0,
123            value: 0,
124        },
125    }
126}
127check_ffi_type!(twz_rt_pre_main_hook);
128
129#[no_mangle]
130pub unsafe extern "C-unwind" fn twz_rt_post_main_hook() {
131    OUR_RUNTIME.post_main_hook()
132}
133check_ffi_type!(twz_rt_post_main_hook);
134
135#[no_mangle]
136pub unsafe extern "C-unwind" fn twz_rt_runtime_entry(
137    arg: *const twizzler_rt_abi::bindings::runtime_info,
138    std_entry: core::option::Option<
139        unsafe extern "C-unwind" fn(
140            arg1: twizzler_rt_abi::bindings::basic_aux,
141        ) -> twizzler_rt_abi::bindings::basic_return,
142    >,
143    main: usize,
144) {
145    OUR_RUNTIME.runtime_entry(arg, std_entry.unwrap_unchecked(), main)
146}
147check_ffi_type!(twz_rt_runtime_entry, _, _, _);
148
149#[no_mangle]
150pub unsafe extern "C-unwind" fn twz_rt_cross_compartment_entry() -> bool {
151    OUR_RUNTIME.cross_compartment_entry().is_ok()
152}
153check_ffi_type!(twz_rt_cross_compartment_entry);
154
155#[no_mangle]
156pub unsafe extern "C-unwind" fn twz_rt_set_upcall_handler(
157    handler: Option<unsafe extern "C-unwind" fn(frame: *mut c_void, data: *const c_void)>,
158) {
159    let _ = set_upcall_handler(handler);
160}
161check_ffi_type!(twz_rt_set_upcall_handler, _);
162
163// alloc.h
164
165use twizzler_rt_abi::bindings::{alloc_flags, ZERO_MEMORY};
166#[no_mangle]
167pub unsafe extern "C-unwind" fn twz_rt_malloc(
168    sz: usize,
169    align: usize,
170    flags: alloc_flags,
171) -> *mut ::core::ffi::c_void {
172    let Ok(layout) = core::alloc::Layout::from_size_align(sz, align) else {
173        return core::ptr::null_mut();
174    };
175    if flags & ZERO_MEMORY != 0 {
176        OUR_RUNTIME.alloc_zeroed(layout).cast()
177    } else {
178        OUR_RUNTIME.alloc(layout).cast()
179    }
180}
181check_ffi_type!(twz_rt_malloc, _, _, _);
182
183#[no_mangle]
184pub unsafe extern "C-unwind" fn twz_rt_dealloc(
185    ptr: *mut ::core::ffi::c_void,
186    sz: usize,
187    align: usize,
188    flags: twizzler_rt_abi::bindings::alloc_flags,
189) {
190    let Ok(layout) = core::alloc::Layout::from_size_align(sz, align) else {
191        return;
192    };
193    if flags & ZERO_MEMORY != 0 {
194        let slice = unsafe { core::slice::from_raw_parts_mut(ptr.cast::<u8>(), sz) };
195        slice.fill(0);
196        core::hint::black_box(slice);
197    }
198    OUR_RUNTIME.dealloc(ptr.cast(), layout);
199}
200check_ffi_type!(twz_rt_dealloc, _, _, _, _);
201
202#[no_mangle]
203pub unsafe extern "C-unwind" fn twz_rt_realloc(
204    ptr: *mut ::core::ffi::c_void,
205    sz: usize,
206    align: usize,
207    new_size: usize,
208    flags: twizzler_rt_abi::bindings::alloc_flags,
209) -> *mut ::core::ffi::c_void {
210    let Ok(layout) = core::alloc::Layout::from_size_align(sz, align) else {
211        return core::ptr::null_mut();
212    };
213    if flags & ZERO_MEMORY != 0 {
214        todo!()
215    }
216    OUR_RUNTIME.realloc(ptr.cast(), layout, new_size).cast()
217}
218check_ffi_type!(twz_rt_realloc, _, _, _, _, _);
219
220// thread.h
221
222#[no_mangle]
223pub unsafe extern "C-unwind" fn twz_rt_futex_wait(
224    ptr: *mut u32,
225    expected: twizzler_rt_abi::bindings::futex_word,
226    timeout: twizzler_rt_abi::bindings::option_duration,
227) -> twizzler_rt_abi::bindings::twz_error {
228    if timeout.is_some != 0 {
229        OUR_RUNTIME.futex_wait(&*ptr.cast(), expected, Some(timeout.dur.into()))
230    } else {
231        OUR_RUNTIME.futex_wait(&*ptr.cast(), expected, None)
232    }
233}
234check_ffi_type!(twz_rt_futex_wait, _, _, _);
235
236#[no_mangle]
237pub unsafe extern "C-unwind" fn twz_rt_futex_wake(
238    ptr: *mut u32,
239    max: i64,
240) -> twizzler_rt_abi::bindings::twz_error {
241    OUR_RUNTIME.futex_wake(&*ptr.cast(), max as usize)
242}
243check_ffi_type!(twz_rt_futex_wake, _, _);
244
245#[no_mangle]
246pub unsafe extern "C-unwind" fn twz_rt_yield_now() {
247    OUR_RUNTIME.yield_now();
248}
249check_ffi_type!(twz_rt_yield_now);
250
251#[no_mangle]
252pub unsafe extern "C-unwind" fn twz_rt_set_name(name: *const ::core::ffi::c_char) {
253    unsafe {
254        OUR_RUNTIME.set_name(core::ffi::CStr::from_ptr(name));
255    }
256}
257check_ffi_type!(twz_rt_set_name, _);
258
259#[no_mangle]
260pub unsafe extern "C-unwind" fn twz_rt_get_name(
261    tcb: *const c_void,
262    name: *mut core::ffi::c_char,
263    len: *mut usize,
264) {
265    unsafe {
266        *len = OUR_RUNTIME.get_name(tcb, core::slice::from_raw_parts_mut(name.cast(), *len));
267    }
268}
269check_ffi_type!(twz_rt_get_name, _, _, _);
270
271#[no_mangle]
272pub unsafe extern "C-unwind" fn twz_rt_sleep(dur: twizzler_rt_abi::bindings::duration) {
273    OUR_RUNTIME.sleep(dur.into());
274}
275check_ffi_type!(twz_rt_sleep, _);
276
277#[no_mangle]
278pub unsafe extern "C-unwind" fn twz_rt_tls_get_addr(
279    index: *mut twizzler_rt_abi::bindings::tls_index,
280) -> *mut ::core::ffi::c_void {
281    OUR_RUNTIME
282        .tls_get_addr(unsafe { &*index })
283        .unwrap_or(core::ptr::null_mut())
284        .cast()
285}
286check_ffi_type!(twz_rt_tls_get_addr, _);
287
288// Provide this for C, since this will be emitted by the C compiler.
289#[no_mangle]
290pub unsafe extern "C-unwind" fn __tls_get_addr(
291    index: *mut twizzler_rt_abi::bindings::tls_index,
292) -> *mut ::core::ffi::c_void {
293    twz_rt_tls_get_addr(index)
294}
295
296#[no_mangle]
297pub unsafe extern "C-unwind" fn twz_rt_spawn_thread(
298    args: twizzler_rt_abi::bindings::spawn_args,
299) -> twizzler_rt_abi::bindings::spawn_result {
300    OUR_RUNTIME.spawn(args).into()
301}
302check_ffi_type!(twz_rt_spawn_thread, _);
303#[no_mangle]
304pub unsafe extern "C-unwind" fn twz_rt_join_thread(
305    id: twizzler_rt_abi::bindings::thread_id,
306    timeout: twizzler_rt_abi::bindings::option_duration,
307) -> twizzler_rt_abi::bindings::twz_error {
308    match if timeout.is_some != 0 {
309        OUR_RUNTIME.join(id, Some(timeout.dur.into()))
310    } else {
311        OUR_RUNTIME.join(id, None)
312    } {
313        Ok(_) => RawTwzError::success().raw(),
314        Err(e) => e.raw(),
315    }
316}
317check_ffi_type!(twz_rt_join_thread, _, _);
318
319// fd.h
320
321use twizzler_rt_abi::bindings::{descriptor, open_kind, open_result};
322#[no_mangle]
323pub unsafe extern "C-unwind" fn twz_rt_fd_open(
324    kind: open_kind,
325    flags: u32,
326    bind_info: *mut c_void,
327    bind_info_len: usize,
328) -> open_result {
329    let Ok(kind) = kind.try_into() else {
330        return Err(ArgumentError::InvalidArgument.into()).into();
331    };
332    OUR_RUNTIME
333        .open(None, kind, flags.into(), bind_info, bind_info_len, true)
334        .into()
335}
336check_ffi_type!(twz_rt_fd_open, _, _, _, _);
337
338#[no_mangle]
339pub unsafe extern "C-unwind" fn twz_rt_fd_reopen(
340    fd: descriptor,
341    kind: open_kind,
342    flags: u32,
343    bind_info: *mut c_void,
344    bind_info_len: usize,
345) -> twz_error {
346    let Ok(kind) = kind.try_into() else {
347        return TwzError::INVALID_ARGUMENT.raw();
348    };
349    match OUR_RUNTIME.open(Some(fd), kind, flags.into(), bind_info, bind_info_len, true) {
350        Ok(_) => RawTwzError::success().raw(),
351        Err(e) => e.raw(),
352    }
353}
354check_ffi_type!(twz_rt_fd_reopen, _, _, _, _, _);
355
356#[no_mangle]
357pub unsafe extern "C-unwind" fn twz_rt_fd_read_binds(
358    binds: *mut binding_info,
359    len: usize,
360) -> usize {
361    let binds = unsafe { core::slice::from_raw_parts_mut(binds, len) };
362    OUR_RUNTIME.read_binds(binds)
363}
364check_ffi_type!(twz_rt_fd_read_binds, _, _);
365
366use core::ffi::c_char;
367
368#[no_mangle]
369pub unsafe extern "C-unwind" fn twz_rt_fd_remove(name: *const c_char, len: usize) -> twz_error {
370    let name = unsafe { core::slice::from_raw_parts(name.cast(), len) };
371    let name = core::str::from_utf8(name).map_err(|_| TwzError::INVALID_ARGUMENT.raw());
372    match name {
373        Ok(name) => match OUR_RUNTIME.remove(name) {
374            Ok(_) => RawTwzError::success().raw(),
375            Err(e) => e.raw(),
376        },
377        Err(e) => e,
378    }
379}
380check_ffi_type!(twz_rt_fd_remove, _, _);
381
382#[no_mangle]
383pub unsafe extern "C-unwind" fn twz_rt_fd_close(fd: descriptor) {
384    OUR_RUNTIME.close(fd);
385}
386check_ffi_type!(twz_rt_fd_close, _);
387
388#[no_mangle]
389pub unsafe extern "C-unwind" fn twz_rt_fd_get_info(
390    fd: descriptor,
391    fd_info: *mut twizzler_rt_abi::bindings::fd_info,
392) -> bool {
393    match OUR_RUNTIME.fd_get_info(fd) {
394        Some(info) => {
395            fd_info.write(info);
396            true
397        }
398        None => false,
399    }
400}
401check_ffi_type!(twz_rt_fd_get_info, _, _);
402
403#[no_mangle]
404pub unsafe extern "C-unwind" fn twz_rt_fd_cmd(
405    fd: descriptor,
406    cmd: twizzler_rt_abi::bindings::fd_cmd,
407    arg: *mut ::core::ffi::c_void,
408    ret: *mut ::core::ffi::c_void,
409) -> twz_error {
410    match OUR_RUNTIME.fd_cmd(fd, cmd, arg.cast(), ret.cast()) {
411        Ok(_) => RawTwzError::success().raw(),
412        Err(e) => e.raw(),
413    }
414}
415check_ffi_type!(twz_rt_fd_cmd, _, _, _, _);
416
417#[no_mangle]
418pub unsafe extern "C-unwind" fn twz_rt_fd_waitpoint(
419    fd: descriptor,
420    kind: wait_kind,
421    point: *mut *mut u64,
422    val: *mut u64,
423    ready: *mut bool,
424) -> twz_error {
425    match OUR_RUNTIME.fd_waitpoint(fd, kind) {
426        Ok((ts, is_ready)) => {
427            point.write(
428                ts.reference
429                    .address()
430                    .unwrap_or(core::ptr::null_mut())
431                    .cast(),
432            );
433            val.write(ts.value);
434            ready.write(is_ready);
435            RawTwzError::success().raw()
436        }
437        Err(e) => e.raw(),
438    }
439}
440check_ffi_type!(twz_rt_fd_waitpoint, _, _, _, _, _);
441
442#[no_mangle]
443pub unsafe extern "C-unwind" fn twz_rt_fd_select(
444    nfds: usize,
445    readfds: *mut fd_set,
446    writefds: *mut fd_set,
447    exceptfds: *mut fd_set,
448    timeout: twizzler_rt_abi::bindings::option_duration,
449) -> io_result {
450    match OUR_RUNTIME.select(
451        nfds,
452        readfds,
453        writefds,
454        exceptfds,
455        if timeout.is_some != 0 {
456            Some(timeout.dur.into())
457        } else {
458            None
459        },
460    ) {
461        Ok(result) => io_result {
462            err: TwzError::SUCCESS.raw(),
463            val: result,
464        },
465        Err(e) => io_result {
466            err: e.raw(),
467            val: 0,
468        },
469    }
470}
471check_ffi_type!(twz_rt_fd_select, _, _, _, _, _);
472
473#[no_mangle]
474pub unsafe extern "C-unwind" fn twz_rt_fd_poll(
475    fds: *mut twizzler_rt_abi::bindings::pollfd,
476    nfds: usize,
477    timeout: twizzler_rt_abi::bindings::option_duration,
478) -> io_result {
479    let fd_slice = unsafe { core::slice::from_raw_parts_mut(fds, nfds) };
480    match OUR_RUNTIME.ppoll(
481        fd_slice,
482        if timeout.is_some != 0 {
483            Some(timeout.dur.into())
484        } else {
485            None
486        },
487        core::ptr::null(),
488    ) {
489        Ok(result) => io_result {
490            err: TwzError::SUCCESS.raw(),
491            val: result,
492        },
493        Err(e) => io_result {
494            err: e.raw(),
495            val: 0,
496        },
497    }
498}
499check_ffi_type!(twz_rt_fd_poll, _, _, _);
500
501#[no_mangle]
502pub unsafe extern "C-unwind" fn twz_rt_fd_enumerate_names(
503    fd: descriptor,
504    buf: *mut twizzler_rt_abi::bindings::name_entry,
505    len: ::core::ffi::c_size_t,
506    off: ::core::ffi::c_size_t,
507) -> io_result {
508    OUR_RUNTIME
509        .fd_enumerate(
510            fd,
511            unsafe { core::slice::from_raw_parts_mut(buf, len) },
512            off,
513        )
514        .into()
515}
516check_ffi_type!(twz_rt_fd_enumerate_names, _, _, _, _);
517
518#[no_mangle]
519pub unsafe extern "C-unwind" fn twz_rt_fd_mkns(name: *const c_char, len: usize) -> twz_error {
520    let name = unsafe { core::slice::from_raw_parts(name.cast(), len) };
521    let name = core::str::from_utf8(name).map_err(|_| TwzError::INVALID_ARGUMENT.raw());
522    match name {
523        Ok(name) => match OUR_RUNTIME.mkns(name) {
524            Ok(_) => RawTwzError::success().raw(),
525            Err(e) => e.raw(),
526        },
527        Err(e) => e,
528    }
529}
530check_ffi_type!(twz_rt_fd_mkns, _, _);
531
532#[no_mangle]
533pub unsafe extern "C-unwind" fn twz_rt_fd_symlink(
534    name: *const c_char,
535    len: usize,
536    target: *const c_char,
537    target_len: usize,
538) -> twz_error {
539    let name = unsafe { core::slice::from_raw_parts(name.cast(), len) };
540    let name = core::str::from_utf8(name).map_err(|_| TwzError::INVALID_ARGUMENT.raw());
541    let target = unsafe { core::slice::from_raw_parts(target.cast(), target_len) };
542    let Ok(target) = core::str::from_utf8(target).map_err(|_| TwzError::INVALID_ARGUMENT.raw())
543    else {
544        return TwzError::INVALID_ARGUMENT.into();
545    };
546    match name {
547        Ok(name) => match OUR_RUNTIME.symlink(name, target) {
548            Ok(_) => RawTwzError::success().raw(),
549            Err(e) => e.raw(),
550        },
551        Err(e) => e,
552    }
553}
554check_ffi_type!(twz_rt_fd_symlink, _, _, _, _);
555
556#[no_mangle]
557pub unsafe extern "C-unwind" fn twz_rt_get_thread_info(
558    id: twizzler_rt_abi::bindings::thread_id,
559) -> twizzler_rt_abi::bindings::thread_info {
560    let id = if id == twizzler_rt_abi::bindings::TWZ_RT_THREAD_ID_SELF {
561        None
562    } else {
563        Some(id)
564    };
565    OUR_RUNTIME.thread_get_info(id)
566}
567check_ffi_type!(twz_rt_get_thread_info, _);
568
569#[no_mangle]
570pub unsafe extern "C-unwind" fn twz_rt_fd_rename(
571    old_name: *const c_char,
572    old_len: usize,
573    new_name: *const c_char,
574    new_len: usize,
575) -> twz_error {
576    let old = unsafe { core::slice::from_raw_parts(old_name.cast(), old_len) };
577    let old = core::str::from_utf8(old).map_err(|_| TwzError::INVALID_ARGUMENT.raw());
578    let new = unsafe { core::slice::from_raw_parts(new_name.cast(), new_len) };
579    let Ok(new) = core::str::from_utf8(new).map_err(|_| TwzError::INVALID_ARGUMENT.raw()) else {
580        return TwzError::INVALID_ARGUMENT.into();
581    };
582    match old {
583        Ok(old) => match OUR_RUNTIME.rename(old, new) {
584            Ok(_) => RawTwzError::success().raw(),
585            Err(e) => e.raw(),
586        },
587        Err(e) => e,
588    }
589}
590check_ffi_type!(twz_rt_fd_rename, _, _, _, _);
591
592#[no_mangle]
593pub unsafe extern "C-unwind" fn twz_rt_fd_readlink(
594    name: *const c_char,
595    len: usize,
596    target: *mut c_char,
597    target_len: usize,
598    read_len: *mut u64,
599) -> twz_error {
600    let name = unsafe { core::slice::from_raw_parts(name.cast(), len) };
601    let name = core::str::from_utf8(name).map_err(|_| TwzError::INVALID_ARGUMENT.raw());
602    let target = unsafe { core::slice::from_raw_parts_mut(target.cast(), target_len) };
603    match name {
604        Ok(name) => match OUR_RUNTIME.readlink(name, target, unsafe { read_len.as_mut().unwrap() })
605        {
606            Ok(_) => RawTwzError::success().raw(),
607            Err(e) => e.raw(),
608        },
609        Err(e) => e,
610    }
611}
612check_ffi_type!(twz_rt_fd_readlink, _, _, _, _, _);
613
614#[no_mangle]
615pub unsafe extern "C-unwind" fn twz_rt_get_nameroot(
616    root: name_root,
617    path: *mut c_char,
618    len: usize,
619) -> io_result {
620    let slice = unsafe { core::slice::from_raw_parts_mut(path.cast::<u8>(), len) };
621    OUR_RUNTIME.get_nameroot(root.into(), slice).into()
622}
623check_ffi_type!(twz_rt_get_nameroot, _, _, _);
624
625#[no_mangle]
626pub unsafe extern "C-unwind" fn twz_rt_set_nameroot(
627    root: name_root,
628    path: *const c_char,
629    len: usize,
630) -> twz_error {
631    let slice = unsafe { core::slice::from_raw_parts(path.cast::<u8>(), len) };
632    match OUR_RUNTIME.set_nameroot(root.into(), slice) {
633        Ok(_) => RawTwzError::success().raw(),
634        Err(e) => e.raw(),
635    }
636}
637check_ffi_type!(twz_rt_set_nameroot, _, _, _);
638
639// io.h
640use twizzler_rt_abi::bindings::{io_result, iovec, whence};
641#[no_mangle]
642pub unsafe extern "C-unwind" fn twz_rt_fd_pread(
643    fd: descriptor,
644    buf: *mut ::core::ffi::c_void,
645    len: usize,
646    ctx: *mut io_ctx,
647) -> io_result {
648    let slice = unsafe { core::slice::from_raw_parts_mut(buf.cast::<u8>(), len) };
649    OUR_RUNTIME.fd_pread(fd, slice, ctx).into()
650}
651check_ffi_type!(twz_rt_fd_pread, _, _, _, _);
652
653#[no_mangle]
654pub unsafe extern "C-unwind" fn twz_rt_fd_pwrite(
655    fd: descriptor,
656    buf: *const ::core::ffi::c_void,
657    len: usize,
658    ctx: *mut io_ctx,
659) -> io_result {
660    let slice = unsafe { core::slice::from_raw_parts(buf.cast::<u8>(), len) };
661    OUR_RUNTIME.fd_pwrite(fd, slice, ctx).into()
662}
663check_ffi_type!(twz_rt_fd_pwrite, _, _, _, _);
664
665#[no_mangle]
666pub unsafe extern "C-unwind" fn twz_rt_fd_pwrite_to(
667    fd: descriptor,
668    buf: *const ::core::ffi::c_void,
669    len: usize,
670    ctx: *mut io_ctx,
671    ep: *const endpoint,
672) -> io_result {
673    let slice = unsafe { core::slice::from_raw_parts(buf.cast::<u8>(), len) };
674    OUR_RUNTIME.fd_pwrite_to(fd, slice, ctx, ep).into()
675}
676check_ffi_type!(twz_rt_fd_pwrite_to, _, _, _, _, _);
677
678#[no_mangle]
679pub unsafe extern "C-unwind" fn twz_rt_fd_pread_from(
680    fd: descriptor,
681    buf: *mut ::core::ffi::c_void,
682    len: usize,
683    ctx: *mut io_ctx,
684    ep: *mut endpoint,
685) -> io_result {
686    let slice = unsafe { core::slice::from_raw_parts_mut(buf.cast::<u8>(), len) };
687    OUR_RUNTIME.fd_pread_from(fd, slice, ctx, ep).into()
688}
689check_ffi_type!(twz_rt_fd_pread_from, _, _, _, _, _);
690
691use twizzler_rt_abi::io::SeekFrom;
692
693fn twz_sf_to_std_sf(sf: SeekFrom) -> std::io::SeekFrom {
694    match sf {
695        SeekFrom::Start(pos) => std::io::SeekFrom::Start(pos),
696        SeekFrom::End(pos) => std::io::SeekFrom::End(pos),
697        SeekFrom::Current(pos) => std::io::SeekFrom::Current(pos),
698    }
699}
700
701#[no_mangle]
702pub unsafe extern "C-unwind" fn twz_rt_fd_seek(
703    fd: descriptor,
704    whence: whence,
705    offset: i64,
706) -> io_result {
707    let seek = match whence {
708        twizzler_rt_abi::bindings::WHENCE_START => SeekFrom::Start(offset as u64),
709        twizzler_rt_abi::bindings::WHENCE_END => SeekFrom::End(offset),
710        twizzler_rt_abi::bindings::WHENCE_CURRENT => SeekFrom::Current(offset),
711        _ => {
712            return io_result {
713                val: 0,
714                err: TwzError::INVALID_ARGUMENT.raw(),
715            }
716        }
717    };
718    OUR_RUNTIME.seek(fd, twz_sf_to_std_sf(seek)).into()
719}
720check_ffi_type!(twz_rt_fd_seek, _, _, _);
721
722#[no_mangle]
723pub unsafe extern "C-unwind" fn twz_rt_fd_preadv(
724    fd: descriptor,
725    iovs: *const iovec,
726    nr_iovs: usize,
727    ctx: *mut io_ctx,
728) -> io_result {
729    let slice = unsafe { core::slice::from_raw_parts(iovs, nr_iovs) };
730    OUR_RUNTIME.fd_preadv(fd, slice, ctx).into()
731}
732check_ffi_type!(twz_rt_fd_preadv, _, _, _, _);
733
734#[no_mangle]
735pub unsafe extern "C-unwind" fn twz_rt_fd_pwritev(
736    fd: descriptor,
737    iovs: *const iovec,
738    nr_iovs: usize,
739    ctx: *mut io_ctx,
740) -> io_result {
741    let slice = unsafe { core::slice::from_raw_parts(iovs, nr_iovs) };
742    OUR_RUNTIME.fd_pwritev(fd, slice, ctx).into()
743}
744check_ffi_type!(twz_rt_fd_pwritev, _, _, _, _);
745
746#[no_mangle]
747pub unsafe extern "C-unwind" fn twz_rt_fd_get_config(
748    fd: descriptor,
749    reg: u32,
750    val: *mut c_void,
751    val_len: usize,
752) -> twz_error {
753    match OUR_RUNTIME.fd_get_config(fd, reg, val, val_len) {
754        Ok(_) => RawTwzError::success().raw(),
755        Err(e) => e.raw(),
756    }
757}
758check_ffi_type!(twz_rt_fd_get_config, _, _, _, _);
759
760#[no_mangle]
761pub unsafe extern "C-unwind" fn twz_rt_fd_set_config(
762    fd: descriptor,
763    reg: u32,
764    val: *const c_void,
765    val_len: usize,
766) -> twz_error {
767    match OUR_RUNTIME.fd_set_config(fd, reg, val, val_len) {
768        Ok(_) => RawTwzError::success().raw(),
769        Err(e) => e.raw(),
770    }
771}
772check_ffi_type!(twz_rt_fd_set_config, _, _, _, _);
773
774#[no_mangle]
775pub unsafe extern "C-unwind" fn twz_rt_resolve_name(
776    resolver: name_resolver,
777    name: *const c_char,
778    name_len: usize,
779) -> objid_result {
780    let slice = unsafe { core::slice::from_raw_parts(name as *const u8, name_len) };
781    result_id_to_bindings(OUR_RUNTIME.resolve_name(resolver.into(), slice))
782}
783check_ffi_type!(twz_rt_resolve_name, _, _, _);
784
785#[no_mangle]
786pub unsafe extern "C-unwind" fn twz_rt_canon_name(
787    resolver: name_resolver,
788    name: *const c_char,
789    name_len: usize,
790    out: *mut c_char,
791    out_len: *mut usize,
792) -> twz_error {
793    let slice = unsafe { core::slice::from_raw_parts(name as *const u8, name_len) };
794    let out_slice = unsafe { core::slice::from_raw_parts_mut(out as *mut u8, out_len.read()) };
795    match OUR_RUNTIME.canon_name(resolver.into(), slice, out_slice) {
796        Ok(len) => {
797            out_len.write(len);
798            RawTwzError::success().raw()
799        }
800        Err(e) => e.raw(),
801    }
802}
803check_ffi_type!(twz_rt_canon_name, _, _, _, _, _);
804
805// object.h
806
807fn result_id_to_bindings(value: Result<ObjID, TwzError>) -> objid_result {
808    match value {
809        Ok(id) => objid_result {
810            err: RawTwzError::success().raw(),
811            __bindgen_padding_0: 0,
812            val: id.raw(),
813        },
814        Err(err) => objid_result {
815            err: err.raw(),
816            __bindgen_padding_0: 0,
817            val: 0,
818        },
819    }
820}
821
822use twizzler_rt_abi::{
823    bindings::{map_flags, map_result, object_handle, objid, objid_result},
824    object::MapFlags,
825};
826#[no_mangle]
827pub unsafe extern "C-unwind" fn twz_rt_create_rtobj() -> objid_result {
828    result_id_to_bindings(OUR_RUNTIME.create_rtobj())
829}
830check_ffi_type!(twz_rt_create_rtobj);
831
832#[unsafe(no_mangle)]
833pub unsafe extern "C-unwind" fn twz_rt_create_object(
834    spec: *const object_create,
835    src: *const object_source,
836    src_len: usize,
837    ties: *const object_tie,
838    tie_len: usize,
839    name: *const c_char,
840    namelen: usize,
841) -> objid_result {
842    let spec = spec.as_ref().unwrap();
843    let src = if !src.is_null() {
844        core::slice::from_raw_parts(src, src_len)
845    } else {
846        &[]
847    };
848    let ties = if !ties.is_null() {
849        core::slice::from_raw_parts(ties, tie_len)
850    } else {
851        &[]
852    };
853    let name_slice = if !name.is_null() {
854        Some(core::slice::from_raw_parts(name.cast(), namelen))
855    } else {
856        None
857    };
858    let name = name_slice.and_then(|name_slice| str::from_utf8(name_slice).ok());
859    result_id_to_bindings(OUR_RUNTIME.create_object(&ObjectCreate::from(*spec), src, ties, name))
860}
861check_ffi_type!(twz_rt_create_object, _, _, _, _, _, _, _);
862
863#[no_mangle]
864pub unsafe extern "C-unwind" fn twz_rt_map_object(id: objid, flags: map_flags) -> map_result {
865    OUR_RUNTIME
866        .map_object(id.into(), MapFlags::from_bits_truncate(flags))
867        .into()
868}
869check_ffi_type!(twz_rt_map_object, _, _);
870
871#[no_mangle]
872pub unsafe extern "C-unwind" fn twz_rt_release_handle(
873    handle: *mut object_handle,
874    flags: release_flags,
875) {
876    OUR_RUNTIME.release_handle(handle, flags)
877}
878check_ffi_type!(twz_rt_release_handle, _, _);
879
880#[no_mangle]
881pub unsafe extern "C-unwind" fn twz_rt_object_cmd(
882    handle: *mut object_handle,
883    cmd: object_cmd,
884    arg: *mut c_void,
885) -> twz_error {
886    match OUR_RUNTIME.object_cmd(handle, cmd, arg) {
887        Ok(_) => 0,
888        Err(e) => e.raw(),
889    }
890}
891check_ffi_type!(twz_rt_object_cmd, _, _, _);
892
893#[no_mangle]
894pub unsafe extern "C-unwind" fn twz_rt_update_handle(handle: *mut object_handle) -> twz_error {
895    match OUR_RUNTIME.update_handle(handle) {
896        Ok(_) => 0,
897        Err(e) => e.raw(),
898    }
899}
900check_ffi_type!(twz_rt_update_handle, _);
901
902#[no_mangle]
903pub unsafe extern "C-unwind" fn twz_rt_get_object_handle(ptr: *mut c_void) -> object_handle {
904    OUR_RUNTIME
905        .get_object_handle_from_ptr(ptr.cast())
906        .unwrap_or(object_handle::default())
907}
908check_ffi_type!(twz_rt_get_object_handle, _);
909
910#[no_mangle]
911pub unsafe extern "C-unwind" fn twz_rt_insert_fot(
912    handle: *mut object_handle,
913    fote: *mut c_void,
914) -> u32_result {
915    OUR_RUNTIME.insert_fot(handle, fote.cast()).into()
916}
917check_ffi_type!(twz_rt_insert_fot, _, _);
918
919#[no_mangle]
920pub unsafe extern "C-unwind" fn twz_rt_resolve_fot(
921    handle: *mut object_handle,
922    idx: u64,
923    valid_len: usize,
924    map_flags: map_flags,
925) -> map_result {
926    OUR_RUNTIME
927        .resolve_fot(
928            handle,
929            idx,
930            valid_len,
931            MapFlags::from_bits_truncate(map_flags),
932        )
933        .into()
934}
935check_ffi_type!(twz_rt_resolve_fot, _, _, _, _);
936
937#[no_mangle]
938pub unsafe extern "C-unwind" fn twz_rt_resolve_fot_local(
939    ptr: *mut c_void,
940    idx: u64,
941    valid_len: usize,
942    map_flags: map_flags,
943) -> *mut c_void {
944    OUR_RUNTIME
945        .resolve_fot_local(
946            ptr.cast(),
947            idx,
948            valid_len,
949            MapFlags::from_bits_truncate(map_flags),
950        )
951        .cast()
952}
953check_ffi_type!(twz_rt_resolve_fot_local, _, _, _, _);
954
955#[no_mangle]
956pub unsafe extern "C-unwind" fn __twz_rt_map_two_objects(
957    id_1: objid,
958    flags_1: map_flags,
959    id_2: objid,
960    flags_2: map_flags,
961    res_1: *mut map_result,
962    res_2: *mut map_result,
963) {
964    unsafe {
965        match OUR_RUNTIME.map_two_objects(
966            id_1.into(),
967            MapFlags::from_bits_truncate(flags_1),
968            id_2.into(),
969            MapFlags::from_bits_truncate(flags_2),
970        ) {
971            Ok((r1, r2)) => {
972                res_1.write(Ok(r1).into());
973                res_2.write(Ok(r2).into());
974            }
975            Err(e) => {
976                res_1.write(Err(e).into());
977                res_2.write(Err(e).into());
978            }
979        }
980    }
981}
982check_ffi_type!(__twz_rt_map_two_objects, _, _, _, _, _, _);
983
984// time.h
985
986use twizzler_rt_abi::bindings::duration;
987#[no_mangle]
988pub unsafe extern "C-unwind" fn twz_rt_get_monotonic_time() -> duration {
989    OUR_RUNTIME.get_monotonic().into()
990}
991check_ffi_type!(twz_rt_get_monotonic_time);
992
993#[no_mangle]
994pub unsafe extern "C-unwind" fn twz_rt_get_system_time() -> duration {
995    OUR_RUNTIME.get_system_time().into()
996}
997check_ffi_type!(twz_rt_get_system_time);
998
999// debug.h
1000
1001use twizzler_rt_abi::bindings::{dl_phdr_info, loaded_image, loaded_image_id};
1002#[no_mangle]
1003pub unsafe extern "C-unwind" fn twz_rt_get_loaded_image(
1004    id: loaded_image_id,
1005    li: *mut loaded_image,
1006) -> bool {
1007    let Some(image_info) = OUR_RUNTIME.get_image_info(id) else {
1008        return false;
1009    };
1010    unsafe {
1011        li.write(image_info);
1012    }
1013    true
1014}
1015check_ffi_type!(twz_rt_get_loaded_image, _, _);
1016
1017#[no_mangle]
1018pub unsafe extern "C-unwind" fn twz_rt_iter_phdr(
1019    cb: ::core::option::Option<
1020        unsafe extern "C-unwind" fn(
1021            arg1: *const dl_phdr_info,
1022            size: usize,
1023            data: *mut ::core::ffi::c_void,
1024        ) -> ::core::ffi::c_int,
1025    >,
1026    data: *mut ::core::ffi::c_void,
1027) -> ::core::ffi::c_int {
1028    OUR_RUNTIME
1029        .iterate_phdr(&mut |info| cb.unwrap()(&info, core::mem::size_of::<dl_phdr_info>(), data))
1030}
1031check_ffi_type!(twz_rt_iter_phdr, _, _);
1032
1033// info.h
1034use twizzler_rt_abi::bindings::system_info;
1035#[no_mangle]
1036pub unsafe extern "C-unwind" fn twz_rt_get_sysinfo() -> system_info {
1037    OUR_RUNTIME.sysinfo()
1038}
1039check_ffi_type!(twz_rt_get_sysinfo);
1040
1041// exec.h
1042
1043#[no_mangle]
1044pub unsafe extern "C-unwind" fn twz_rt_exec_spawn(
1045    args: *const twizzler_rt_abi::bindings::exec_spawn_args,
1046) -> open_result {
1047    OUR_RUNTIME.exec_spawn(args.as_ref().unwrap()).into()
1048}
1049check_ffi_type!(twz_rt_exec_spawn, _);
1050
1051// random.h
1052
1053use twizzler_rt_abi::bindings::get_random_flags;
1054#[no_mangle]
1055pub unsafe extern "C-unwind" fn twz_rt_get_random(
1056    buf: *mut ::core::ffi::c_char,
1057    len: usize,
1058    flags: get_random_flags,
1059) -> usize {
1060    OUR_RUNTIME.get_random(
1061        unsafe { core::slice::from_raw_parts_mut(buf.cast(), len) },
1062        flags.into(),
1063    )
1064}
1065check_ffi_type!(twz_rt_get_random, _, _, _);
1066
1067// additional definitions for C
1068#[linkage = "weak"]
1069#[no_mangle]
1070pub unsafe extern "C-unwind" fn malloc(len: usize) -> *mut core::ffi::c_void {
1071    warn!("called c:malloc with len = {}: not yet implemented", len);
1072    core::ptr::null_mut()
1073}
1074
1075#[linkage = "weak"]
1076#[no_mangle]
1077pub unsafe extern "C-unwind" fn free(ptr: *mut core::ffi::c_void) {
1078    warn!("called c:free with ptr = {:p}: not yet implemented", ptr);
1079}
1080
1081#[linkage = "weak"]
1082#[no_mangle]
1083pub unsafe extern "C-unwind" fn getenv(name: *const core::ffi::c_char) -> *const core::ffi::c_char {
1084    let n = unsafe { CStr::from_ptr(name.cast()) };
1085    OUR_RUNTIME.cgetenv(n)
1086}
1087
1088#[no_mangle]
1089pub unsafe extern "C-unwind" fn dl_iterate_phdr(
1090    cb: ::core::option::Option<
1091        unsafe extern "C-unwind" fn(
1092            arg1: *const dl_phdr_info,
1093            size: usize,
1094            data: *mut ::core::ffi::c_void,
1095        ) -> ::core::ffi::c_int,
1096    >,
1097    data: *mut core::ffi::c_void,
1098) -> i32 {
1099    twz_rt_iter_phdr(cb, data)
1100}
1101
1102#[linkage = "weak"]
1103#[no_mangle]
1104pub unsafe extern "C-unwind" fn fwrite(
1105    ptr: *const core::ffi::c_void,
1106    len: usize,
1107    nitems: usize,
1108    file: *const core::ffi::c_void,
1109) -> usize {
1110    twz_rt_fd_pwrite(1, ptr, len * nitems, core::ptr::null_mut());
1111    len * nitems
1112}
1113
1114#[linkage = "weak"]
1115#[unsafe(no_mangle)]
1116pub unsafe extern "C-unwind" fn fprintf(
1117    file: *const core::ffi::c_void,
1118    fmt: *const core::ffi::c_char,
1119    args: ...
1120) -> i32 {
1121    use printf_compat::{format, output};
1122    let mut s = String::new();
1123    let bytes_written = format(fmt.cast(), args, output::fmt_write(&mut s));
1124    twz_rt_fd_pwrite(
1125        1,
1126        s.as_bytes().as_ptr().cast(),
1127        s.as_bytes().len(),
1128        core::ptr::null_mut(),
1129    );
1130    bytes_written
1131}
1132
1133#[no_mangle]
1134pub unsafe extern "C-unwind" fn __monitor_get_slot() -> isize {
1135    match OUR_RUNTIME.allocate_slot() {
1136        Some(s) => s.try_into().unwrap_or(-1),
1137        None => -1,
1138    }
1139}
1140
1141#[no_mangle]
1142pub unsafe extern "C-unwind" fn __monitor_release_slot(slot: usize) {
1143    OUR_RUNTIME.release_slot(slot);
1144}
1145
1146#[no_mangle]
1147pub unsafe extern "C-unwind" fn __monitor_release_pair(one: usize, two: usize) {
1148    OUR_RUNTIME.release_pair((one, two));
1149}
1150
1151#[no_mangle]
1152pub unsafe extern "C-unwind" fn __monitor_get_slot_pair(one: *mut usize, two: *mut usize) -> bool {
1153    let Some((a, b)) = OUR_RUNTIME.allocate_pair() else {
1154        return false;
1155    };
1156    one.write(a);
1157    two.write(b);
1158    true
1159}
1160
1161#[no_mangle]
1162pub unsafe extern "C-unwind" fn __monitor_ready() {
1163    OUR_RUNTIME.set_runtime_ready();
1164}
1165
1166#[no_mangle]
1167pub unsafe extern "C-unwind" fn __is_monitor_ready() -> bool {
1168    OUR_RUNTIME.state().contains(crate::RuntimeState::READY)
1169}
1170
1171#[no_mangle]
1172pub unsafe extern "C-unwind" fn __is_monitor() -> *mut c_void {
1173    OUR_RUNTIME.is_monitor().unwrap_or(core::ptr::null_mut())
1174}
1175
1176#[linkage = "weak"]
1177#[no_mangle]
1178pub unsafe extern "C-unwind" fn _ZdlPv() {}
1179
1180#[linkage = "weak"]
1181#[no_mangle]
1182pub unsafe extern "C-unwind" fn _ZdlPvj() {}
1183
1184#[linkage = "weak"]
1185#[no_mangle]
1186pub unsafe extern "C-unwind" fn _ZdlPvm() {}
1187
1188#[linkage = "weak"]
1189#[unsafe(no_mangle)]
1190pub unsafe extern "C" fn __dlapi_error() -> *const c_char {
1191    take_dl_error()
1192}
1193
1194use core::ffi::c_int;
1195use std::cell::RefCell;
1196
1197#[thread_local]
1198static DLAPI_ERROR: RefCell<Option<std::ffi::CString>> = const { RefCell::new(None) };
1199
1200fn set_dl_error(msg: impl Into<Vec<u8>>) {
1201    *DLAPI_ERROR.borrow_mut() = std::ffi::CString::new(msg).ok();
1202}
1203
1204fn take_dl_error() -> *const c_char {
1205    DLAPI_ERROR
1206        .borrow_mut()
1207        .take()
1208        .map(|s| s.into_raw() as *const c_char)
1209        .unwrap_or(core::ptr::null())
1210}
1211
1212/// The __dlapi_symbol struct as defined by mlibc's dlfcn.cpp.
1213#[repr(C)]
1214struct DlapiSymbol {
1215    file: *const c_char,
1216    base: *mut c_void,
1217    symbol: *const c_char,
1218    address: *mut c_void,
1219    elf_symbol: *const c_void,
1220    link_map: *mut c_void,
1221}
1222
1223/// Encode a `Descriptor` as a non-null `void*` handle (offset by 1 so descriptor 0 != NULL).
1224fn desc_to_handle(desc: secgate::util::Descriptor) -> *mut c_void {
1225    (desc as usize + 1) as *mut c_void
1226}
1227
1228/// Decode a handle back to a descriptor. Returns `None` for NULL (RTLD_DEFAULT).
1229fn handle_to_desc(handle: *const c_void) -> Option<secgate::util::Descriptor> {
1230    let v = handle as usize;
1231    if v == 0 {
1232        None
1233    } else {
1234        Some((v - 1) as secgate::util::Descriptor)
1235    }
1236}
1237
1238#[linkage = "weak"]
1239#[unsafe(no_mangle)]
1240pub unsafe extern "C" fn __dlapi_open(
1241    filename: *const c_char,
1242    _flags: c_int,
1243    _return_addr: *const c_void,
1244) -> *mut c_void {
1245    //twizzler_abi::klog_println!("called __dlapi_open with filename = {:p}", filename);
1246    if filename.is_null() {
1247        return core::ptr::null_mut(); // RTLD_DEFAULT sentinel
1248    }
1249    let name = match unsafe { std::ffi::CStr::from_ptr(filename) }.to_str() {
1250        Ok(s) => s,
1251        Err(_) => {
1252            set_dl_error("dlopen: invalid UTF-8 in filename");
1253            return core::ptr::null_mut();
1254        }
1255    };
1256    let id = OUR_RUNTIME
1257        .resolve_name(twizzler_rt_abi::fd::NameResolver::Default, name.as_bytes())
1258        .ok();
1259    match monitor_api::LibraryLoader::new(name, id).load() {
1260        Ok(desc) => desc_to_handle(desc.into_raw()),
1261        Err(e) => {
1262            set_dl_error(format!("dlopen: library '{}' not found: {:?}", name, e));
1263            core::ptr::null_mut()
1264        }
1265    }
1266}
1267
1268#[linkage = "weak"]
1269#[unsafe(no_mangle)]
1270pub unsafe extern "C" fn __dlapi_resolve(
1271    handle: *const c_void,
1272    symbol: *const c_char,
1273    _return_addr: *const c_void,
1274    _version: *const c_char,
1275) -> *mut c_void {
1276    let sym_name = match unsafe { std::ffi::CStr::from_ptr(symbol) }.to_str() {
1277        Ok(s) => s,
1278        Err(_) => {
1279            set_dl_error("dlsym: invalid UTF-8 in symbol name");
1280            return core::ptr::null_mut();
1281        }
1282    };
1283    let lib_desc = handle_to_desc(handle);
1284    match monitor_api::lookup_symbol_by_name(lib_desc, sym_name) {
1285        Ok(addr) if addr != 0 => addr as *mut c_void,
1286        Ok(_) => {
1287            set_dl_error(format!("dlsym: symbol '{}' resolved to NULL", sym_name));
1288            core::ptr::null_mut()
1289        }
1290        Err(e) => {
1291            set_dl_error(format!("dlsym: symbol '{}' not found: {:?}", sym_name, e));
1292            core::ptr::null_mut()
1293        }
1294    }
1295}
1296
1297#[linkage = "weak"]
1298#[unsafe(no_mangle)]
1299pub unsafe extern "C" fn __dlapi_reverse(
1300    ptr: *const c_void,
1301    out: *mut c_void, // actually *mut DlapiSymbol
1302) -> c_int {
1303    //twizzler_abi::klog_println!("called __dlapi_reverse with ptr = {:p}", ptr);
1304    if out.is_null() {
1305        return 1;
1306    }
1307    let out = unsafe { &mut *(out as *mut DlapiSymbol) };
1308
1309    // Iterate libraries in the current compartment until we find one whose mapped
1310    // range contains `ptr`.
1311    let mut lib_n: usize = 0;
1312    loop {
1313        let desc = match monitor_api::monitor_rt_get_library_handle(None, lib_n) {
1314            Ok(d) => d,
1315            Err(_) => break,
1316        };
1317        let raw = match monitor_api::monitor_rt_get_library_info(desc) {
1318            Ok(r) => r,
1319            Err(_) => {
1320                let _ = monitor_api::monitor_rt_drop_library_handle(desc);
1321                break;
1322            }
1323        };
1324        let lib_info = monitor_api::LibraryInfo::from_raw(raw);
1325        let base = lib_info.dl_info.addr as *const u8;
1326        let len = lib_info.len;
1327
1328        if !base.is_null()
1329            && (ptr as usize) >= (base as usize)
1330            && (ptr as usize) < (base as usize + MAX_SIZE * 2)
1331        {
1332            // TODO: this leaks.
1333            let name_cstring = std::ffi::CString::new(lib_info.name.clone()).unwrap_or_default();
1334            let name_ptr: *const c_char = name_cstring.into_raw();
1335            let _ = monitor_api::monitor_rt_drop_library_handle(desc);
1336            out.file = name_ptr;
1337            out.base = base as *mut c_void;
1338            out.symbol = core::ptr::null();
1339            out.address = core::ptr::null_mut();
1340            out.elf_symbol = core::ptr::null();
1341            out.link_map = lib_info.link_map.0.ld.cast();
1342            return 0;
1343        }
1344
1345        let _ = monitor_api::monitor_rt_drop_library_handle(desc);
1346        lib_n += 1;
1347    }
1348    1 // not found
1349}
1350
1351#[linkage = "weak"]
1352#[unsafe(no_mangle)]
1353pub unsafe extern "C" fn __dlapi_close(handle: *const c_void) -> c_int {
1354    if handle.is_null() {
1355        return 0;
1356    }
1357    let Some(desc) = handle_to_desc(handle) else {
1358        return 0;
1359    };
1360    match monitor_api::monitor_rt_drop_library_handle(desc) {
1361        Ok(()) => 0,
1362        Err(_) => 1,
1363    }
1364}
1365
1366#[linkage = "weak"]
1367#[unsafe(no_mangle)]
1368pub unsafe extern "C" fn __dlapi_find_object() -> *const c_char {
1369    twizzler_abi::klog_println!("called __dlapi_find_object: not yet implemented");
1370    core::ptr::null()
1371}
1372
1373#[linkage = "weak"]
1374#[unsafe(no_mangle)]
1375pub unsafe extern "C" fn __dlapi_get_tls() -> *const c_char {
1376    twizzler_abi::klog_println!("called __dlapi_get_tls: not yet implemented");
1377    core::ptr::null()
1378}