std crate builds with stubs

This commit is contained in:
ahgamut 2022-06-22 09:25:13 +05:30
parent 26c4c14d96
commit f6ae82160c
6 changed files with 117 additions and 52 deletions

2
.gitignore vendored
View file

@ -4,6 +4,8 @@
# download cosmo amalgamation
/libcosmo/*
!/libcosmo/README.md
!/libcosmo/compile-stubs.bash
!/libcosmo/stubs.c
# Generated by Cargo
# will have compiled files and executables

View file

@ -51,63 +51,21 @@ objcopy -SO binary ./target/x86_64-unknown-linux-cosmo/debug/hello_world.com.dbg
## What about the `std` crate?
The `std` crate compiles successfully, but fails at the linker stage. Here's how
that can be tested:
1. It needs a few stubs functions so the linker doesn't complain. I wrote them
out in `stubs.c`.
1. Change the source code in `src/main.rs` to use the commented out `main`
function and `#![restricted_std]`.
2. In the source code for Rust's `std` crate, change a `cfg_if` in
`$HOME/.rustup/toolchains/<your-host-nightly-toolchain>/lib/rustlib/src/rust/library/backtrace/src/backtrace/mod.rs`
to use the `noop` trace instead of depending on `libunwind`.
```diff
--- mod.rs 2022-06-21 12:52:21.724053459 +0530
+++ mod.rs 2022-06-21 13:05:50.948777093 +0530
@@ -132,7 +132,7 @@
pub(crate) mod miri;
use self::miri::trace as trace_imp;
pub(crate) use self::miri::Frame as FrameImp;
- } else if #[cfg(
+ } /* else if #[cfg(
any(
all(
unix,
@@ -154,7 +154,7 @@
pub(crate) use self::dbghelp::Frame as FrameImp;
#[cfg(target_env = "msvc")] // only used in dbghelp symbolize
pub(crate) use self::dbghelp::StackFrame;
- } else {
+ } */ else {
mod noop;
use self::noop::trace as trace_imp;
pub(crate) use self::noop::Frame as FrameImp;
```bash
cd ./libcosmo/
# compiling a simple stub file via cosmopolitan.h
./compile-stubs.bash
```
I haven't figured out what config I should give to `cargo` so I don't need to do
this. I find it surprising that `std` cannot be built without relying on
`libunwind`.
3. The build command now changes to
2. The build command now changes to
```bash
cargo +nightly build -Zbuild-std=core,alloc,panic_abort,libc,std -Zbuild-std-features= --target=./x86_64-unknown-linux-cosmo.json
```
4. At the linker stage you might find some of the following symbols are missing:
- If `Unwind_Backtrace` or similar is missing, you need to check if step 2 is
done properly.
- `open64`, `stat64`, `fstat64`, `__xpg_strerror_r`: these can be added to
Cosmopolitan Libc via aliases of the existing functions.
- `pthread_key_create`,`pthread_setspecific`,`pthread_key_delete`,`pthread_getspecific`
-- these functions should not be needed in a single-threaded program, but
somehow they are still linked. Support for threads is currently being added
to Cosmopolitan Libc, but possibly the related code in the `std` crate can
be changed to avoid this issue.
[rust]: https://rust-lang.org
[cosmo]: https://github.com/jart/cosmopolitan
[amalg-download]: https://justine.lol/cosmopolitan/download.html

7
libcosmo/compile-stubs.bash Executable file
View file

@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -eux
gcc -g -Os -static -nostdlib -nostdinc \
-fno-pie -no-pie -mno-red-zone \
-fno-omit-frame-pointer -pg -mnop-mcount \
-o ./stubs.o -c ./stubs.c

98
libcosmo/stubs.c Normal file
View file

@ -0,0 +1,98 @@
#include "cosmopolitan.h"
typedef enum {
_URC_NO_REASON = 0,
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
_URC_FATAL_PHASE2_ERROR = 2,
_URC_FATAL_PHASE1_ERROR = 3,
_URC_NORMAL_STOP = 4,
_URC_END_OF_STACK = 5,
_URC_HANDLER_FOUND = 6,
_URC_INSTALL_CONTEXT = 7,
_URC_CONTINUE_UNWIND = 8
} _Unwind_Reason_Code;
#define UNW_TDEP_CURSOR_LEN 127
typedef uint64_t unw_word_t;
typedef struct unw_cursor {
unw_word_t opaque[UNW_TDEP_CURSOR_LEN];
} unw_cursor_t;
struct _Unwind_Context {
unw_cursor_t cursor;
int end_of_stack;
};
typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context *,
void *);
uintptr_t _Unwind_GetCFA(struct _Unwind_Context *ctx) {
return 0;
}
uintptr_t _Unwind_GetIP(struct _Unwind_Context *ctx) {
return 0;
}
_Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn fn, void *arg) {
return _URC_NORMAL_STOP;
}
void *_Unwind_FindEnclosingFunction(void *arg) {
return NULL;
}
#define MAX_KEYS 64
typedef unsigned pthread_key_t;
typedef void (*dtor)(void*);
typedef struct {
pthread_key_t kval;
dtor d;
void *value;
} tls_t;
static tls_t my_tls[MAX_KEYS] = {0};
static unsigned thread_avail = 0;
int pthread_key_create(pthread_key_t *k, dtor destructor) {
for(pthread_key_t i=1; i<MAX_KEYS; i++) {
if(my_tls[i].kval == 0) {
*k = i;
my_tls[i].kval = i;
my_tls[i].d = destructor;
return 0;
}
}
return -1;
}
void* pthread_getspecific(pthread_key_t k) {
if(k < MAX_KEYS) {
return my_tls[k].value;
}
return NULL;
}
int pthread_setspecific(pthread_key_t k, const void* value) {
if(k < MAX_KEYS) {
my_tls[k].value = value;
return 0;
}
return -1;
}
int pthread_key_delete(pthread_key_t k) {
if (k < MAX_KEYS) {
my_tls[k].kval = 0;
return 0;
}
return -1;
}
int __xpg_strerror_r(int a, char *b, size_t c) {
return strerror_r(a, b, c);
}

View file

@ -1,3 +1,4 @@
/*
#![no_main]
#![no_std]
#![feature(rustc_private)]
@ -20,12 +21,10 @@ pub extern "C" fn main(_argc: isize, _argv: *const *const u8) -> isize {
fn my_panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}
/* std crate requires some external changes
*/
#![feature(restricted_std)]
pub fn main() {
println!("hello pls cosmo rust APE");
}
*/

View file

@ -49,6 +49,7 @@
"-fuse-ld=bfd",
"-Wl,-T,./libcosmo/ape.lds",
"./libcosmo/crt.o",
"./libcosmo/stubs.o",
"./libcosmo/ape-no-modify-self.o",
"./libcosmo/cosmopolitan.a"
]