diff --git a/src/c/dlmalloc.c b/src/c/dlmalloc.c index 8ae1f7a39098ff0821194827af7344def34a5150..6ad2b06274d7e5f1861b5d282cc81fccfd455635 100644 --- a/src/c/dlmalloc.c +++ b/src/c/dlmalloc.c @@ -523,7 +523,8 @@ MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP /* Customizations { */ -#define HAVE_MMAP 0 +#define HAVE_MMAP 1 +#define ONLY_MSPACES 1 #define LACKS_ERRNO_H #define LACKS_FCNTL_H #define LACKS_SCHED_H @@ -536,7 +537,7 @@ MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP #define USE_DL_PREFIX 1 #define USE_LOCKS 1 #define USE_SPIN_LOCKS 1 - +#define HAVE_MREMAP 0 #define malloc_getpagesize ((size_t)4096U) #include <stddef.h> @@ -545,7 +546,22 @@ MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP #define EINVAL 22 extern __thread int errno; - +#if defined(__linux__) +#define O_RDWR 2 +#define PROT_READ 1 +#define PROT_WRITE 2 +#elif defined(__redox__) +#define O_RDWR 196608 +#define PROT_READ 4 +#define PROT_WRITE 2 +#endif /*defined(__redox__)*/ + +#define MAP_PRIVATE 2 +typedef long off_t; + +int open(const char *pathname, int flags); +void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off); +int munmap(void *addr, size_t len); void abort(void); void *memcpy(void *dest, const void *src, size_t n); void *memset(void *s, int c, size_t n); diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs index 6b54a35a663cf8bd272ab74b99b58e4cdf03e6db..3f3e1911b87e3bc8a27acc923bf566a20c6cbe66 100644 --- a/src/ld_so/linker.rs +++ b/src/ld_so/linker.rs @@ -694,7 +694,11 @@ impl Linker { set_u64(tm as u64); } reloc::R_X86_64_DTPOFF64 => { - set_u64((s - b) as u64); + if s != 0 { + set_u64((s - b) as u64); + } else { + set_u64(s as u64); + } } reloc::R_X86_64_GLOB_DAT | reloc::R_X86_64_JUMP_SLOT => { set_u64(s as u64); diff --git a/src/ld_so/start.rs b/src/ld_so/start.rs index 92e83a3bd15f18cefdb734322ffacfc478c64b0b..0ff6d5300efc67f4d91bdc540f1c6ce5ed72828e 100644 --- a/src/ld_so/start.rs +++ b/src/ld_so/start.rs @@ -3,7 +3,12 @@ use alloc::{borrow::ToOwned, boxed::Box, collections::BTreeMap, string::String, vec::Vec}; use crate::{ - c_str::CStr, header::unistd, platform::types::c_char, start::Stack, sync::mutex::Mutex, + c_str::CStr, + header::unistd, + platform::{new_mspace, types::c_char}, + start::Stack, + sync::mutex::Mutex, + ALLOCATOR, }; use super::{ @@ -116,7 +121,9 @@ unsafe fn adjust_stack(sp: &'static mut Stack) { } #[no_mangle] pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) -> usize { - // first we get the arguments, the environment, and the auxilary vector + // First thing we initialize the mspace + ALLOCATOR.set_book_keeper(new_mspace()); + // next we get the arguments, the environment, and the auxilary vector let (argv, envs, auxv) = unsafe { let argv_start = sp.argv() as *mut usize; let (argv, argv_end) = get_argv(argv_start); @@ -210,6 +217,7 @@ pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) -> } if let Some(tcb) = unsafe { Tcb::current() } { tcb.linker_ptr = Box::into_raw(Box::new(Mutex::new(linker))); + tcb.mspace = ALLOCATOR.get_book_keeper(); } if is_manual { eprintln!("ld.so: entry '{}': {:#x}", path, entry); diff --git a/src/ld_so/tcb.rs b/src/ld_so/tcb.rs index 3a303088827e2e3b4d01dcb0bdac2131bb302b0f..c859903a51fe1d280012cdaa59e688dd8066b174 100644 --- a/src/ld_so/tcb.rs +++ b/src/ld_so/tcb.rs @@ -45,6 +45,8 @@ pub struct Tcb { pub masters_len: usize, /// Pointer to dynamic linker pub linker_ptr: *const Mutex<Linker>, + /// pointer to rust memory allocator structure + pub mspace: usize, } impl Tcb { @@ -64,6 +66,7 @@ impl Tcb { masters_ptr: ptr::null_mut(), masters_len: 0, linker_ptr: ptr::null(), + mspace: 0, }, ); diff --git a/src/lib.rs b/src/lib.rs index 589ccb38ab2357acafeb48df61e6217a7fc18709..9425e7d14bff7fbd90f405d9679fc47919d69231 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,10 +59,10 @@ pub mod platform; pub mod start; pub mod sync; -use crate::platform::{Allocator, Pal, Sys}; +use crate::platform::{Allocator, Pal, Sys, NEWALLOCATOR}; #[global_allocator] -static ALLOCATOR: Allocator = Allocator; +static ALLOCATOR: Allocator = NEWALLOCATOR; #[no_mangle] pub extern "C" fn relibc_panic(pi: &::core::panic::PanicInfo) -> ! { diff --git a/src/platform/allocator/dlmalloc.rs b/src/platform/allocator/dlmalloc.rs index a5a890f7d37418c9e9d6cfedc23c3edfd53d7692..a3d718d43b6f5c3e34ab2b3d7acea709c1ac40df 100644 --- a/src/platform/allocator/dlmalloc.rs +++ b/src/platform/allocator/dlmalloc.rs @@ -1,16 +1,39 @@ -use core::alloc::{GlobalAlloc, Layout}; +use core::{ + alloc::{GlobalAlloc, Layout}, + sync::atomic::{AtomicUsize, Ordering}, +}; +use crate::ALLOCATOR; use super::types::*; extern "C" { - fn dlmalloc(bytes: size_t) -> *mut c_void; - fn dlmemalign(alignment: size_t, bytes: size_t) -> *mut c_void; - fn dlrealloc(oldmem: *mut c_void, bytes: size_t) -> *mut c_void; - fn dlfree(mem: *mut c_void); + fn create_mspace(capacity: size_t, locked: c_int) -> usize; + fn mspace_malloc(msp: usize, bytes: size_t) -> *mut c_void; + fn mspace_memalign(msp: usize, alignment: size_t, bytes: size_t) -> *mut c_void; + fn mspace_realloc(msp: usize, oldmem: *mut c_void, bytes: size_t) -> *mut c_void; + fn mspace_free(msp: usize, mem: *mut c_void); + //fn dlmalloc(bytes: size_t) -> *mut c_void; + //fn dlmemalign(alignment: size_t, bytes: size_t) -> *mut c_void; + //fn dlrealloc(oldmem: *mut c_void, bytes: size_t) -> *mut c_void; + //fn dlfree(mem: *mut c_void); } -pub struct Allocator; +pub struct Allocator { + mstate: AtomicUsize, +} + +pub const NEWALLOCATOR: Allocator = Allocator { + mstate: AtomicUsize::new(0), +}; +impl Allocator { + pub fn set_book_keeper(&self, mstate: usize) { + self.mstate.store(mstate, Ordering::Relaxed); + } + pub fn get_book_keeper(&self) -> usize { + self.mstate.load(Ordering::Relaxed) + } +} unsafe impl<'a> GlobalAlloc for Allocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { alloc_align(layout.size(), layout.align()) as *mut u8 @@ -22,17 +45,21 @@ unsafe impl<'a> GlobalAlloc for Allocator { } pub unsafe fn alloc(size: usize) -> *mut c_void { - dlmalloc(size) + mspace_malloc(ALLOCATOR.get_book_keeper(), size) } pub unsafe fn alloc_align(size: usize, alignment: usize) -> *mut c_void { - dlmemalign(alignment, size) + mspace_memalign(ALLOCATOR.get_book_keeper(), alignment, size) } pub unsafe fn realloc(ptr: *mut c_void, size: size_t) -> *mut c_void { - dlrealloc(ptr, size) + mspace_realloc(ALLOCATOR.get_book_keeper(), ptr, size) } pub unsafe fn free(ptr: *mut c_void) { - dlfree(ptr) + mspace_free(ALLOCATOR.get_book_keeper(), ptr) +} + +pub fn new_mspace() -> usize { + unsafe { create_mspace(0, 0) } } diff --git a/src/platform/pte.rs b/src/platform/pte.rs index c6ca0fba4a9b5a5976061f9d8af86b5f254df985..d36a163b06191809a9c2c03bddba33f0c9399e73 100644 --- a/src/platform/pte.rs +++ b/src/platform/pte.rs @@ -17,6 +17,7 @@ use crate::{ Pal, Sys, }, sync::Mutex, + ALLOCATOR, }; pub struct Semaphore { @@ -76,6 +77,7 @@ unsafe extern "C" fn pte_osThreadShim( tls_masters_ptr: *mut Master, tls_masters_len: usize, tls_linker_ptr: *const Mutex<Linker>, + tls_mspace: usize, ) { // The kernel allocated TLS does not have masters set, so do not attempt to copy it. // It will be copied by the kernel. @@ -84,6 +86,7 @@ unsafe extern "C" fn pte_osThreadShim( tcb.masters_ptr = tls_masters_ptr; tcb.masters_len = tls_masters_len; tcb.linker_ptr = tls_linker_ptr; + tcb.mspace = tls_mspace; tcb.copy_masters().unwrap(); tcb.activate(); } @@ -134,11 +137,13 @@ pub unsafe extern "C" fn pte_osThreadCreate( push(0); if let Some(tcb) = Tcb::current() { + push(tcb.mspace as usize); push(tcb.linker_ptr as usize); push(tcb.masters_len); push(tcb.masters_ptr as usize); push(tcb.tls_len); } else { + push(ALLOCATOR.get_book_keeper()); push(0); push(0); push(0); diff --git a/src/start.rs b/src/start.rs index 3dd856f59fd54a2d3b718111cfc6a78b0841faad..f3b0769ff67ac90ac1ac019286195c4adf2c8e6e 100644 --- a/src/start.rs +++ b/src/start.rs @@ -4,7 +4,8 @@ use core::{intrinsics, ptr}; use crate::{ header::{stdio, stdlib}, ld_so, - platform::{self, types::*, Pal, Sys}, + platform::{self, new_mspace, types::*, Pal, Sys}, + ALLOCATOR, }; #[repr(C)] @@ -66,7 +67,26 @@ static INIT_ARRAY: [extern "C" fn(); 1] = [init_array]; static mut init_complete: bool = false; +fn alloc_init() { + unsafe{ + if let Some(tcb) = ld_so::tcb::Tcb::current() { + if tcb.mspace != 0 { + ALLOCATOR.set_book_keeper(tcb.mspace); + } else if ALLOCATOR.get_book_keeper() == 0 { + ALLOCATOR.set_book_keeper(new_mspace()); + } + } else if ALLOCATOR.get_book_keeper() == 0 { + ALLOCATOR.set_book_keeper(new_mspace()); + } + } +} + extern "C" fn init_array() { + // The thing is that we cannot guarantee if + // init_array runs first or if relibc_start runs first + // Still whoever gets to run first must initialize rust + // memory allocator before doing anything else. + alloc_init(); io_init(); unsafe { init_complete = true }; } @@ -92,6 +112,9 @@ pub unsafe extern "C" fn relibc_start(sp: &'static Stack) -> ! { fn _init(); fn main(argc: isize, argv: *mut *mut c_char, envp: *mut *mut c_char) -> c_int; } + // Step 1 setup the right allocator... + // if any memory rust based memory allocation happen before this step .. we are doomed. + alloc_init(); // Ensure correct host system before executing more system calls relibc_verify_host();