...
 
Commits (7)
This diff is collapsed.
......@@ -11,6 +11,7 @@ fn main() {
.flag("-I")
.flag(&format!("{}/include", crate_dir))
.flag("-fno-stack-protector")
.file("src/c/dlmalloc.c")
.file("src/c/fcntl.c")
.file("src/c/stdio.c")
.compile("relibc_c");
......
Subproject commit 867c809039aef77dbce22e98b1009b8995dfa868
Subproject commit f9b8c35fe8a58c0216b06d24832408fe2d9c0206
This diff is collapsed.
......@@ -47,5 +47,3 @@ int execle(const char *path, const char* argv0, ...)
return execve(path, argv, envp);
}
}
#endif
......@@ -5,6 +5,7 @@
#![feature(linkage)]
#![feature(naked_functions)]
#![feature(panic_implementation)]
#![feature(lang_items)]
extern crate platform;
......@@ -51,6 +52,8 @@ impl Stack {
#[inline(never)]
#[no_mangle]
pub unsafe extern "C" fn _start_rust(sp: &'static Stack) -> ! {
use core::fmt::Write;
extern "C" {
fn main(argc: isize, argv: *const *const u8) -> c_int;
}
......@@ -72,3 +75,19 @@ pub extern "C" fn rust_begin_unwind(pi: &::core::panic::PanicInfo) -> ! {
platform::exit(1);
}
#[lang = "oom"]
#[linkage = "weak"]
#[no_mangle]
pub extern "C" fn rust_oom(layout: ::core::alloc::Layout) -> ! {
use core::fmt::Write;
let mut w = platform::FileWriter(2);
let _ = w.write_fmt(format_args!(
"RELIBC OOM: {} bytes aligned to {} bytes\n",
layout.size(),
layout.align()
));
platform::exit(1);
}
......@@ -3,6 +3,11 @@ name = "platform"
version = "0.1.0"
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
[dependencies.ralloc]
path = "../../ralloc"
default-features = false
optional = true
[target.'cfg(target_os = "linux")'.dependencies]
sc = "0.2"
......
use core::alloc::{GlobalAlloc, Layout};
use 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);
}
pub struct Allocator;
unsafe impl<'a> GlobalAlloc for Allocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
dlmemalign(layout.align(), layout.size()) as *mut u8
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
dlfree(ptr as *mut c_void)
}
}
pub unsafe fn alloc(size: usize) -> *mut c_void {
dlmalloc(size)
}
pub unsafe fn alloc_align(size: usize, alignment: usize) -> *mut c_void {
dlmemalign(alignment, size)
}
pub unsafe fn realloc(ptr: *mut c_void, size: size_t) -> *mut c_void {
dlrealloc(ptr, size)
}
pub unsafe fn free(ptr: *mut c_void) {
dlfree(ptr)
}
extern crate ralloc;
pub use ralloc::Allocator;
unsafe fn alloc_inner(size: usize, offset: usize, align: usize) -> *mut c_void {
let ptr = ralloc::alloc(size + offset, align);
if !ptr.is_null() {
*(ptr as *mut u64) = (size + offset) as u64;
*(ptr as *mut u64).offset(1) = align as u64;
ptr.offset(offset as isize) as *mut c_void
} else {
ptr as *mut c_void
}
}
pub unsafe fn alloc(size: usize) -> *mut c_void {
alloc_inner(size, 16, 8)
}
pub unsafe fn alloc_align(size: usize, alignment: usize) -> *mut c_void {
let mut align = 32;
while align <= alignment {
align *= 2;
}
alloc_inner(size, align/2, align)
}
pub unsafe fn realloc(ptr: *mut c_void, size: size_t) -> *mut c_void {
let old_ptr = (ptr as *mut u8).offset(-16);
let old_size = *(old_ptr as *mut u64);
let align = *(old_ptr as *mut u64).offset(1);
let ptr = ralloc::realloc(old_ptr, old_size as usize, size + 16, align as usize);
if !ptr.is_null() {
*(ptr as *mut u64) = (size + 16) as u64;
*(ptr as *mut u64).offset(1) = align;
ptr.offset(16) as *mut c_void
} else {
ptr as *mut c_void
}
}
pub unsafe fn free(ptr: *mut c_void) {
let ptr = (ptr as *mut u8).offset(-16);
let size = *(ptr as *mut u64);
let _align = *(ptr as *mut u64).offset(1);
ralloc::free(ptr, size as usize);
}
//! fcntl implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/fcntl.h.html
#![no_std]
#![allow(non_camel_case_types)]
#![feature(alloc)]
#![feature(allocator_api)]
//TODO #![feature(thread_local)]
extern crate alloc;
#[cfg(all(not(feature = "no_std"), target_os = "linux"))]
#[macro_use]
extern crate sc;
......@@ -12,6 +14,16 @@ extern crate sc;
#[macro_use]
pub extern crate syscall;
pub use allocator::*;
#[cfg(not(feature = "ralloc"))]
#[path = "allocator/dlmalloc.rs"]
mod allocator;
#[cfg(feature = "ralloc")]
#[path = "allocator/ralloc.rs"]
mod allocator;
pub use sys::*;
#[cfg(all(not(feature = "no_std"), target_os = "linux"))]
......@@ -28,6 +40,9 @@ use core::fmt;
use types::*;
#[global_allocator]
static ALLOCATOR: Allocator = Allocator;
//TODO #[thread_local]
#[allow(non_upper_case_globals)]
#[no_mangle]
......
......@@ -19,15 +19,8 @@ pub fn e(sys: usize) -> usize {
}
}
pub fn brk(addr: *const c_void) -> c_int {
unsafe {
let newbrk = syscall!(BRK, addr);
if newbrk < addr as usize {
-1
} else {
0
}
}
pub fn brk(addr: *mut c_void) -> *mut c_void {
unsafe { syscall!(BRK, addr) as *mut c_void }
}
pub fn chdir(path: *const c_char) -> c_int {
......
......@@ -22,8 +22,8 @@ pub fn e(sys: Result<usize, syscall::Error>) -> usize {
}
}
pub fn brk(addr: *const c_void) -> c_int {
e(unsafe { syscall::brk(addr as usize) }) as c_int
pub fn brk(addr: *mut c_void) -> *mut c_void {
unsafe { syscall::brk(addr as usize).unwrap_or(0) as *mut c_void }
}
pub fn chdir(path: *const c_char) -> c_int {
......@@ -72,6 +72,71 @@ pub fn exit(status: c_int) -> ! {
loop {}
}
pub unsafe extern "C" fn execve(
path: *const c_char,
argv: *const *mut c_char,
envp: *const *mut c_char,
) -> c_int {
use alloc::Vec;
use syscall::flag::*;
let mut env = envp;
while !(*env).is_null() {
let slice = c_str(*env);
// Should always contain a =, but worth checking
if let Some(sep) = slice.iter().position(|&c| c == b'=') {
// If the environment variable has no name, do not attempt
// to add it to the env.
if sep > 0 {
let mut path = b"env:".to_vec();
path.extend_from_slice(&slice[..sep]);
match syscall::open(&path, O_WRONLY | O_CREAT) {
Ok(fd) => {
// If the environment variable has no value, there
// is no need to write anything to the env scheme.
if sep + 1 < slice.len() {
let n = match syscall::write(fd, &slice[sep + 1..]) {
Ok(n) => n,
err => {
return e(err) as c_int;
}
};
}
// Cleanup after adding the variable.
match syscall::close(fd) {
Ok(_) => (),
err => {
return e(err) as c_int;
}
}
}
err => {
return e(err) as c_int;
}
}
}
}
env = env.offset(1);
}
let mut len = 0;
for i in 0.. {
if (*argv.offset(i)).is_null() {
len = i;
break;
}
}
let mut args: Vec<[usize; 2]> = Vec::with_capacity(len as usize);
let mut arg = argv;
while !(*arg).is_null() {
args.push([*arg as usize, c_str(*arg).len()]);
arg = arg.offset(1);
}
e(syscall::execve(c_str(path), &args)) as c_int
}
pub fn fchdir(fd: c_int) -> c_int {
let path: &mut [u8] = &mut [0; 4096];
if e(syscall::fpath(fd as usize, path)) == !0 {
......
......@@ -12,6 +12,5 @@ errno = { path = "../errno"}
fcntl = { path = "../fcntl" }
lazy_static = { version = "*", features = ["nightly", "spin_no_std"] }
platform = { path = "../platform" }
ralloc = { path = "../../ralloc", default-features = false }
string = { path = "../string" }
va_list = { path = "../../va_list", features = ["no_std"] }
......@@ -6,7 +6,6 @@ use errno;
use fcntl::*;
use platform;
use platform::types::*;
use ralloc;
/// Parse mode flags as a string and output a mode flags integer
pub unsafe fn parse_mode_flags(mode_str: *const c_char) -> i32 {
......@@ -63,7 +62,7 @@ pub unsafe fn _fdopen(fd: c_int, mode: *const c_char) -> Option<*mut FILE> {
flags |= F_APP;
}
let f = ralloc::alloc(mem::size_of::<FILE>(), 1) as *mut FILE;
let f = platform::alloc(mem::size_of::<FILE>()) as *mut FILE;
// Allocate the file
if f.is_null() {
None
......
......@@ -12,7 +12,6 @@ extern crate fcntl;
#[macro_use]
extern crate lazy_static;
extern crate platform;
extern crate ralloc;
extern crate string;
extern crate va_list as vl;
......@@ -238,15 +237,13 @@ pub extern "C" fn cuserid(_s: *mut c_char) -> *mut c_char {
/// prior to using this function.
#[no_mangle]
pub extern "C" fn fclose(stream: &mut FILE) -> c_int {
use ralloc::free;
flockfile(stream);
let r = helpers::fflush_unlocked(stream) | platform::close(stream.fd);
if stream.flags & constants::F_PERM == 0 {
// Not one of stdin, stdout or stderr
unsafe {
free(
stream as *mut _ as *mut _,
mem::size_of::<FILE>() + BUFSIZ + UNGET,
platform::free(
stream as *mut FILE as *mut c_void
);
}
} else {
......
......@@ -9,10 +9,9 @@ cbindgen = { path = "../../cbindgen" }
[dependencies]
platform = { path = "../platform" }
ralloc = { path = "../../ralloc", default-features = false }
ctype = { path = "../ctype" }
errno = { path = "../errno" }
rand = { version = "0.5.2", default-features = false }
time = { path = "../time" }
wchar = { path = "../wchar" }
string = { path = "../string" }
\ No newline at end of file
string = { path = "../string" }
......@@ -6,7 +6,6 @@
extern crate ctype;
extern crate errno;
extern crate platform;
extern crate ralloc;
extern crate rand;
extern crate string;
extern crate time;
......@@ -25,9 +24,6 @@ use platform::types::*;
mod sort;
#[global_allocator]
static ALLOCATOR: ralloc::Allocator = ralloc::Allocator;
pub const EXIT_FAILURE: c_int = 1;
pub const EXIT_SUCCESS: c_int = 0;
pub const RAND_MAX: c_int = 2147483647;
......@@ -233,7 +229,7 @@ pub extern "C" fn erand(xsubi: [c_ushort; 3]) -> c_double {
}
#[no_mangle]
pub unsafe extern "C" fn exit(status: c_int) {
pub unsafe extern "C" fn exit(status: c_int) -> ! {
for i in (0..ATEXIT_FUNCS.len()).rev() {
if let Some(func) = ATEXIT_FUNCS[i] {
(func)();
......@@ -255,10 +251,7 @@ pub extern "C" fn fcvt(
#[no_mangle]
pub unsafe extern "C" fn free(ptr: *mut c_void) {
let ptr = (ptr as *mut u8).offset(-16);
let size = *(ptr as *mut u64);
let _align = *(ptr as *mut u64).offset(1);
ralloc::free(ptr, size as usize);
platform::free(ptr);
}
#[no_mangle]
......@@ -333,30 +326,14 @@ pub extern "C" fn lrand48() -> c_long {
unimplemented!();
}
unsafe fn malloc_inner(size: usize, offset: usize, align: usize) -> *mut c_void {
let ptr = ralloc::alloc(size + offset, align);
if !ptr.is_null() {
*(ptr as *mut u64) = (size + offset) as u64;
*(ptr as *mut u64).offset(1) = align as u64;
ptr.offset(offset as isize) as *mut c_void
} else {
ptr as *mut c_void
}
}
#[no_mangle]
pub unsafe extern "C" fn malloc(size: size_t) -> *mut c_void {
malloc_inner(size, 16, 8)
platform::alloc(size)
}
#[no_mangle]
pub unsafe extern "C" fn memalign(alignment: size_t, size: size_t) -> *mut c_void {
let mut align = 32;
while align <= alignment as usize {
align *= 2;
}
malloc_inner(size, align / 2, align)
platform::alloc_align(size, alignment)
}
#[no_mangle]
......@@ -511,17 +488,7 @@ pub extern "C" fn random() -> c_long {
#[no_mangle]
pub unsafe extern "C" fn realloc(ptr: *mut c_void, size: size_t) -> *mut c_void {
let old_ptr = (ptr as *mut u8).offset(-16);
let old_size = *(old_ptr as *mut u64);
let align = *(old_ptr as *mut u64).offset(1);
let ptr = ralloc::realloc(old_ptr, old_size as usize, size + 16, align as usize);
if !ptr.is_null() {
*(ptr as *mut u64) = (size + 16) as u64;
*(ptr as *mut u64).offset(1) = align;
ptr.offset(16) as *mut c_void
} else {
ptr as *mut c_void
}
platform::realloc(ptr, size)
}
#[no_mangle]
......@@ -832,15 +799,7 @@ pub extern "C" fn unlockpt(fildes: c_int) -> c_int {
#[no_mangle]
pub unsafe extern "C" fn valloc(size: size_t) -> *mut c_void {
let align = 4096;
let ptr = ralloc::alloc(size + 16, align);
if !ptr.is_null() {
*(ptr as *mut u64) = (size + 16) as u64;
*(ptr as *mut u64).offset(1) = align as u64;
ptr.offset(16) as *mut c_void
} else {
ptr as *mut c_void
}
memalign(4096, size)
}
#[no_mangle]
......
......@@ -9,5 +9,4 @@ cbindgen = { path = "../../cbindgen" }
[dependencies]
platform = { path = "../platform" }
ralloc = { path = "../../ralloc", default-features = false }
errno = { path = "../errno" }
......@@ -3,7 +3,6 @@
extern crate errno;
extern crate platform;
extern crate ralloc;
use core::cmp;
use core::mem;
......@@ -192,7 +191,7 @@ pub unsafe extern "C" fn strndup(s1: *const c_char, size: usize) -> *mut c_char
let len = strnlen(s1, size);
// the "+ 1" is to account for the NUL byte
let buffer = ralloc::alloc(len + 1, 1) as *mut c_char;
let buffer = platform::alloc(len + 1) as *mut c_char;
if buffer.is_null() {
platform::errno = ENOMEM as c_int;
} else {
......
......@@ -8,6 +8,7 @@ build = "build.rs"
cbindgen = { path = "../../cbindgen" }
[dependencies]
errno = { path = "../errno" }
platform = { path = "../platform" }
stdio = { path = "../stdio" }
string = { path = "../string" }
......
use core::ptr;
use errno::ENOMEM;
use platform;
use platform::types::*;
static mut BRK: *mut c_void = ptr::null_mut();
#[no_mangle]
pub unsafe extern "C" fn brk(addr: *mut c_void) -> c_int {
BRK = platform::brk(addr);
if BRK < addr {
platform::errno = ENOMEM;
return -1;
}
0
}
#[no_mangle]
pub unsafe extern "C" fn sbrk(incr: intptr_t) -> *mut c_void {
if BRK == ptr::null_mut() {
BRK = platform::brk(ptr::null_mut());
}
let old_brk = BRK;
if incr != 0 {
let addr = old_brk.offset(incr);
BRK = platform::brk(addr);
if BRK < addr {
platform::errno = ENOMEM;
return -1isize as *mut c_void
}
}
old_brk as *mut c_void
}
......@@ -5,16 +5,19 @@
#[cfg(target_os = "redox")]
extern crate alloc;
extern crate errno;
extern crate platform;
extern crate stdio;
extern crate string;
extern crate sys_utsname;
pub use brk::*;
pub use getopt::*;
pub use platform::types::*;
use core::ptr;
mod brk;
mod getopt;
pub const R_OK: c_int = 1;
......@@ -53,11 +56,6 @@ pub extern "C" fn alarm(seconds: c_uint) -> c_uint {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn brk(addr: *mut c_void) -> c_int {
platform::brk(addr)
}
#[no_mangle]
pub extern "C" fn chdir(path: *const c_char) -> c_int {
platform::chdir(path)
......@@ -133,72 +131,7 @@ pub unsafe extern "C" fn execve(
argv: *const *mut c_char,
envp: *const *mut c_char,
) -> c_int {
#[cfg(target_os = "linux")]
{
platform::execve(path, argv, envp)
}
#[cfg(target_os = "redox")]
{
use alloc::Vec;
use platform::syscall::flag::*;
use platform::{c_str, e};
let mut env = envp;
while !(*env).is_null() {
let slice = c_str(*env);
// Should always contain a =, but worth checking
if let Some(sep) = slice.iter().position(|&c| c == b'=') {
// If the environment variable has no name, do not attempt
// to add it to the env.
if sep > 0 {
let mut path = b"env:".to_vec();
path.extend_from_slice(&slice[..sep]);
match platform::syscall::open(&path, O_WRONLY | O_CREAT) {
Ok(fd) => {
// If the environment variable has no value, there
// is no need to write anything to the env scheme.
if sep + 1 < slice.len() {
let n = match platform::syscall::write(fd, &slice[sep + 1..]) {
Ok(n) => n,
err => {
return e(err) as c_int;
}
};
}
// Cleanup after adding the variable.
match platform::syscall::close(fd) {
Ok(_) => (),
err => {
return e(err) as c_int;
}
}
}
err => {
return e(err) as c_int;
}
}
}
}
env = env.offset(1);
}
let mut len = 0;
for i in 0.. {
if (*argv.offset(i)).is_null() {
len = i;
break;
}
}
let mut args: Vec<[usize; 2]> = Vec::with_capacity(len as usize);
let mut arg = argv;
while !(*arg).is_null() {
args.push([*arg as usize, c_str(*arg).len()]);
arg = arg.offset(1);
}
e(platform::syscall::execve(c_str(path), &args)) as c_int
}
platform::execve(path, argv, envp)
}
#[no_mangle]
......@@ -469,11 +402,6 @@ pub extern "C" fn rmdir(path: *const c_char) -> c_int {
platform::rmdir(path)
}
#[no_mangle]
pub extern "C" fn sbrk(incr: intptr_t) -> *mut c_void {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn setgid(gid: gid_t) -> c_int {
platform::setregid(gid, gid)
......