mirror of
https://github.com/ahgamut/rust-ape-example.git
synced 2024-12-21 22:56:29 +00:00
std crate builds with stubs
This commit is contained in:
parent
26c4c14d96
commit
f6ae82160c
6 changed files with 117 additions and 52 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -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
|
||||
|
|
56
README.md
56
README.md
|
@ -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
7
libcosmo/compile-stubs.bash
Executable 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
98
libcosmo/stubs.c
Normal 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);
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -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"
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue