libc/wip: add code to install ygglibc
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
int main() {
|
||||
char buf[512];
|
||||
int v = 1234 + 3;
|
||||
snprintf(buf, sizeof(buf), "Hello %d\n", v);
|
||||
printf("Hello!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
/llvm-project
|
||||
/prefix
|
||||
/sysroot
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef _ASSERT_H
|
||||
#define _ASSERT_H 1
|
||||
|
||||
#define __ASSERT_VOID_CAST (void)
|
||||
|
||||
#define assert(expr) \
|
||||
((expr) ? __ASSERT_VOID_CAST(0) : __assert_fail(__FILE__, __LINE__, #expr))
|
||||
|
||||
[[noreturn]] void __assert_fail(const char *file, int line, const char *message);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef _YGGDRASIL_LOCALE_H
|
||||
#define _YGGDRASIL_LOCALE_H 1
|
||||
|
||||
#define LC_GLOBAL_LOCALE ((locale_t) -1L)
|
||||
|
||||
#endif
|
||||
@@ -5,7 +5,7 @@ use core::{
|
||||
use libyalloc::{allocator::BucketAllocator, sys::PageProvider};
|
||||
use yggdrasil_rt::{mem::MappingSource, sys as syscall};
|
||||
|
||||
use crate::error::EResult;
|
||||
use crate::{error::EResult, headers::errno};
|
||||
|
||||
struct Allocator;
|
||||
struct PageProviderImpl;
|
||||
@@ -45,28 +45,41 @@ impl PageProvider for PageProviderImpl {
|
||||
|
||||
const MALLOC_HEADER_SIZE: usize = size_of::<usize>();
|
||||
|
||||
fn c_alloc(size: usize, mut align: usize, zero: bool) -> EResult<NonNull<c_void>> {
|
||||
// assert!(align.is_power_of_two());
|
||||
// if align < align_of::<usize>() {
|
||||
// align = align_of::<usize>();
|
||||
// }
|
||||
// let offset = (MALLOC_HEADER_SIZE + align - 1) & !(align - 1);
|
||||
// let size = offset + size;
|
||||
// let layout = Layout::from_size_align(size, align).ok()?;
|
||||
unsafe fn get_allocation(ptr: NonNull<u8>) -> (NonNull<u8>, Layout) {
|
||||
assert!(usize::from(ptr.addr()) > 0x10);
|
||||
let real_ptr = ptr.sub(MALLOC_HEADER_SIZE);
|
||||
let size = *real_ptr.cast::<usize>().as_ref();
|
||||
let layout = Layout::from_size_align(size, 16).unwrap();
|
||||
(real_ptr, layout)
|
||||
}
|
||||
|
||||
// let ptr = unsafe { YALLOC.allocate(layout) }?;
|
||||
pub fn c_alloc(size: usize, mut align: usize, zero: bool) -> EResult<NonNull<c_void>> {
|
||||
assert!(align.is_power_of_two());
|
||||
if align < align_of::<usize>() {
|
||||
align = align_of::<usize>();
|
||||
}
|
||||
if align > 16 {
|
||||
todo!()
|
||||
}
|
||||
let offset = (MALLOC_HEADER_SIZE + align - 1) & !(align - 1);
|
||||
let size = offset + size;
|
||||
let layout = Layout::from_size_align(size, align).unwrap();
|
||||
|
||||
// if zero {
|
||||
// // TODO
|
||||
// }
|
||||
let ptr = match unsafe { YALLOC.allocate(layout) } {
|
||||
Some(value) => value,
|
||||
None => return EResult::Err(errno::ENOMEM),
|
||||
};
|
||||
|
||||
// unsafe {
|
||||
// // Write the size right below the pointer
|
||||
// ptr.add(offset - size_of::<usize>()).cast::<usize>().write(size);
|
||||
// }
|
||||
if zero {
|
||||
// TODO
|
||||
}
|
||||
|
||||
todo!()
|
||||
// unsafe { Some(ptr.cast::<c_void>().add(offset)) }
|
||||
unsafe {
|
||||
// Write the size right below the pointer
|
||||
ptr.add(offset - size_of::<usize>()).cast::<usize>().write(size);
|
||||
}
|
||||
|
||||
unsafe { EResult::Ok(ptr.cast::<c_void>().add(offset)) }
|
||||
}
|
||||
|
||||
pub unsafe fn malloc(size: usize) -> EResult<NonNull<c_void>> {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
sys_includes = ["stddef.h"]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_LOCALE_H"
|
||||
trailer = "#include <bits/locale.h>"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
include = ["lconv", "locale_t"]
|
||||
@@ -0,0 +1,88 @@
|
||||
use core::{
|
||||
ffi::{c_char, c_int},
|
||||
ptr::null_mut,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct lconv {
|
||||
pub currency_symbol: *mut c_char,
|
||||
pub decimal_point: *mut c_char,
|
||||
pub frac_digits: c_char,
|
||||
pub grouping: *mut c_char,
|
||||
pub int_curr_symbol: *mut c_char,
|
||||
pub int_frac_digits: c_char,
|
||||
pub int_n_cs_precedes: c_char,
|
||||
pub int_n_sep_by_space: c_char,
|
||||
pub int_n_sign_posn: c_char,
|
||||
pub int_p_cs_precedes: c_char,
|
||||
pub int_p_sep_by_space: c_char,
|
||||
pub int_p_sign_posn: c_char,
|
||||
pub mon_decimal_point: *mut c_char,
|
||||
pub mon_grouping: *mut c_char,
|
||||
pub mon_thousands_sep: *mut c_char,
|
||||
pub negative_sign: *mut c_char,
|
||||
pub n_cs_precedes: c_char,
|
||||
pub n_sep_by_space: c_char,
|
||||
pub n_sign_posn: c_char,
|
||||
pub positive_sign: *mut c_char,
|
||||
pub p_cs_precedes: c_char,
|
||||
pub p_sep_by_space: c_char,
|
||||
pub p_sign_posn: c_char,
|
||||
pub thousands_sep: *mut c_char,
|
||||
}
|
||||
|
||||
pub struct __locale_data {}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct __locale_struct {
|
||||
pub __locales: [*mut __locale_data; __LC_LAST],
|
||||
}
|
||||
|
||||
pub type locale_t = *mut __locale_struct;
|
||||
|
||||
pub const LC_COLLATE: c_int = 0;
|
||||
pub const LC_CTYPE: c_int = 1;
|
||||
pub const LC_MESSAGES: c_int = 2;
|
||||
pub const LC_MONETARY: c_int = 3;
|
||||
pub const LC_NUMERIC: c_int = 4;
|
||||
pub const LC_TIME: c_int = 5;
|
||||
|
||||
pub const LC_ALL: c_int = 6;
|
||||
pub const __LC_LAST: usize = 6;
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn duplocale(locobj: locale_t) -> locale_t {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn freelocale(locobj: locale_t) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn localeconv() -> *mut lconv {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn newlocale(
|
||||
category_mask: c_int,
|
||||
locale: *const c_char,
|
||||
base: locale_t,
|
||||
) -> locale_t {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn setlocale(category: c_int, locale: *const c_char) -> *mut c_char {
|
||||
// TODO
|
||||
null_mut()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn uselocale(locobj: locale_t) -> locale_t {
|
||||
todo!()
|
||||
}
|
||||
@@ -1,8 +1,94 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
// <aio.h> -
|
||||
// <arpa/inet.h> -
|
||||
// <assert.h> -
|
||||
// <complex.h> -
|
||||
// <cpio.h> -
|
||||
// <ctype.h> -
|
||||
// <dirent.h> -
|
||||
// <dlfcn.h> -
|
||||
// <errno.h> ~
|
||||
// <fcntl.h> -
|
||||
// <fenv.h> -
|
||||
// <float.h> -
|
||||
// <fmtmsg.h> -
|
||||
// <fnmatch.h> -
|
||||
// <ftw.h> -
|
||||
// <glob.h> -
|
||||
// <grp.h> -
|
||||
// <iconv.h> -
|
||||
// <inttypes.h> -
|
||||
// <iso646.h> -
|
||||
// <langinfo.h> -
|
||||
// <libgen.h> -
|
||||
// <limits.h> -
|
||||
// <locale.h> ~
|
||||
// <math.h> -
|
||||
// <monetary.h> -
|
||||
// <mqueue.h> -
|
||||
// <ndbm.h> -
|
||||
// <net/if.h> -
|
||||
// <netdb.h> -
|
||||
// <netinet/in.h> -
|
||||
// <netinet/tcp.h> -
|
||||
// <nl_types.h> -
|
||||
// <poll.h> -
|
||||
// <pthread.h> -
|
||||
// <pwd.h> -
|
||||
// <regex.h> -
|
||||
// <sched.h> -
|
||||
// <search.h> -
|
||||
// <semaphore.h> -
|
||||
// <setjmp.h> -
|
||||
// <signal.h> -
|
||||
// <spawn.h> -
|
||||
// <stdarg.h> -
|
||||
// <stdbool.h> -
|
||||
// <stddef.h> -
|
||||
// <stdint.h> -
|
||||
// <stdio.h> ~
|
||||
// <stdlib.h> -
|
||||
// <string.h> -
|
||||
// <strings.h> -
|
||||
// <stropts.h> -
|
||||
// <sys/ipc.h> -
|
||||
// <sys/mman.h> -
|
||||
// <sys/msg.h> -
|
||||
// <sys/resource.h> -
|
||||
// <sys/select.h> -
|
||||
// <sys/sem.h> -
|
||||
// <sys/shm.h> -
|
||||
// <sys/socket.h> -
|
||||
// <sys/stat.h> -
|
||||
// <sys/statvfs.h> -
|
||||
// <sys/time.h> -
|
||||
// <sys/times.h> -
|
||||
// <sys/types.h> -
|
||||
// <sys/uio.h> -
|
||||
// <sys/un.h> -
|
||||
// <sys/utsname.h> -
|
||||
// <sys/wait.h> -
|
||||
// <syslog.h> -
|
||||
// <tar.h> -
|
||||
// <termios.h> -
|
||||
// <tgmath.h> -
|
||||
// <time.h> -
|
||||
// <trace.h> -
|
||||
// <ulimit.h> -
|
||||
// <unistd.h> ~
|
||||
// <utime.h> -
|
||||
// <utmpx.h> -
|
||||
// <wchar.h> -
|
||||
// <wctype.h> -
|
||||
// <wordexp.h> -
|
||||
|
||||
pub mod errno;
|
||||
pub mod locale;
|
||||
pub mod stdio;
|
||||
pub mod stdlib;
|
||||
pub mod string;
|
||||
pub mod unistd;
|
||||
pub mod strings;
|
||||
|
||||
pub mod sys_types;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use core::ffi::{c_char, c_int, c_void};
|
||||
|
||||
use crate::{
|
||||
error::CUsizeResult,
|
||||
io::{managed::FILE, Read, Write},
|
||||
util::PointerExt,
|
||||
error::{CEofResult, CUsizeResult},
|
||||
io::{managed::{stdout, FILE}, Read, Write},
|
||||
util::{PointerExt, PointerStrExt},
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
@@ -115,8 +115,12 @@ unsafe extern "C" fn putchar_unlocked(ch: c_int) -> c_int {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn puts(str: *const c_char) -> c_int {
|
||||
todo!()
|
||||
unsafe extern "C" fn puts(str: *const c_char) -> CEofResult {
|
||||
let str = str.ensure_cstr();
|
||||
let out = stdout.ensure_mut();
|
||||
out.write_all(str.to_bytes())?;
|
||||
out.write_all(b"\n")?;
|
||||
CEofResult::success(0)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
||||
@@ -23,4 +23,3 @@ pub type fpos_t = u64;
|
||||
pub const BUFSIZ: usize = 8192;
|
||||
|
||||
const UNGETC_MAX: usize = 128;
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
language = "C"
|
||||
style = "Type"
|
||||
|
||||
sys_includes = ["stddef.h", "locale.h", "strings.h"]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_STRING_H"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
@@ -0,0 +1,71 @@
|
||||
|
||||
use core::{ffi::{c_int, c_void}, ptr::null_mut};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn memccpy(
|
||||
dst: *mut c_void,
|
||||
src: *const c_void,
|
||||
c: c_int,
|
||||
mut n: usize,
|
||||
) -> *mut c_void {
|
||||
let c = c as u8;
|
||||
let mut dst = dst as *mut u8;
|
||||
let mut src = src as *mut u8;
|
||||
|
||||
if dst.is_null() || src.is_null() {
|
||||
panic!();
|
||||
}
|
||||
|
||||
while n != 0 {
|
||||
let ch = *src;
|
||||
*dst = ch;
|
||||
dst = dst.add(1);
|
||||
|
||||
if ch == c {
|
||||
return dst as _;
|
||||
}
|
||||
|
||||
src = src.add(1);
|
||||
n -= 1;
|
||||
}
|
||||
|
||||
null_mut()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn memchr(s: *const c_void, c: c_int, mut n: usize) -> *mut c_void {
|
||||
if s.is_null() {
|
||||
panic!();
|
||||
}
|
||||
|
||||
let c = c as u8;
|
||||
let mut s = s as *const u8;
|
||||
|
||||
while n != 0 {
|
||||
if *s == c {
|
||||
return s as _;
|
||||
}
|
||||
s = s.add(1);
|
||||
n -= 1;
|
||||
}
|
||||
|
||||
null_mut()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub(super) unsafe extern "C" fn mempcpy(
|
||||
dst: *mut c_void,
|
||||
src: *const c_void,
|
||||
n: usize,
|
||||
) -> *mut c_void {
|
||||
if dst.is_null() || src.is_null() {
|
||||
panic!();
|
||||
}
|
||||
let dst = dst as *mut u8;
|
||||
let src = src as *const u8;
|
||||
|
||||
for i in 0..n {
|
||||
*dst.add(i) = *src.add(i);
|
||||
}
|
||||
dst.add(n) as _
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
use core::ffi::{c_char, c_int, c_void};
|
||||
|
||||
pub mod mem;
|
||||
pub mod str;
|
||||
|
||||
extern "C" {
|
||||
pub fn strlen(s: *const c_char) -> usize;
|
||||
pub fn memset(a: *mut c_void, c: c_int, n: usize) -> *mut c_void;
|
||||
pub fn memcpy(dst: *mut c_void, src: *const c_void, n: usize) -> *mut c_void;
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
use core::{
|
||||
cmp::Ordering,
|
||||
ffi::{c_char, c_int},
|
||||
ptr::null_mut,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
allocator,
|
||||
error::CPtrResult,
|
||||
headers::{
|
||||
errno::{self, Errno},
|
||||
locale::locale_t,
|
||||
},
|
||||
};
|
||||
|
||||
use super::{mem::mempcpy, memcpy, memset, strlen};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn stpcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char {
|
||||
if dst.is_null() || src.is_null() {
|
||||
panic!();
|
||||
}
|
||||
let ptr = mempcpy(dst as _, src as _, strlen(src)) as *mut c_char;
|
||||
*ptr = 0;
|
||||
ptr
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn stpncpy(dst: *mut c_char, src: *const c_char, n: usize) -> *mut c_char {
|
||||
if dst.is_null() || src.is_null() {
|
||||
panic!();
|
||||
}
|
||||
memset(dst as _, 0, n);
|
||||
mempcpy(dst as _, src as _, strnlen(src, n)) as _
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strcat(dst: *mut c_char, src: *const c_char) -> *mut c_char {
|
||||
if dst.is_null() {
|
||||
panic!();
|
||||
}
|
||||
stpcpy(dst.add(strlen(dst)), src);
|
||||
dst
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strchr(mut s: *const c_char, c: c_int) -> *mut c_char {
|
||||
if s.is_null() {
|
||||
panic!();
|
||||
}
|
||||
|
||||
loop {
|
||||
if *s == c as _ {
|
||||
return s as _;
|
||||
}
|
||||
|
||||
if *s == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
s = s.add(1);
|
||||
}
|
||||
|
||||
null_mut()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strcmp(a: *const c_char, b: *const c_char) -> c_int {
|
||||
strncmp(a, b, usize::MAX)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char {
|
||||
stpcpy(dst, src);
|
||||
dst
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strcspn(mut s: *const c_char, reject: *const c_char) -> usize {
|
||||
if s.is_null() || reject.is_null() {
|
||||
panic!();
|
||||
}
|
||||
let mut n = 0;
|
||||
while *s != 0 {
|
||||
if !strchr(reject, *s as _).is_null() {
|
||||
return n;
|
||||
}
|
||||
n += 1;
|
||||
s = s.add(1);
|
||||
}
|
||||
n
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strdup(s: *const c_char) -> CPtrResult<c_char> {
|
||||
let len = strlen(s);
|
||||
let data = allocator::c_alloc(len + 1, 1, false)?;
|
||||
memcpy(data.cast().as_ptr(), s as _, len + 1);
|
||||
CPtrResult::success(data.cast())
|
||||
}
|
||||
|
||||
unsafe fn strerror_inner(e: c_int) -> *const c_char {
|
||||
if let Some(errno) = Errno::from_c_int(e) {
|
||||
errno.to_c_str()
|
||||
} else {
|
||||
errno::UNKNOWN_ERROR.as_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strerror(e: c_int) -> *mut c_char {
|
||||
static mut BUF: [c_char; 128] = [0; 128];
|
||||
#[allow(static_mut_refs)]
|
||||
strerror_r(e, BUF.as_mut_ptr(), BUF.len())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strerror_r(e: c_int, buf: *mut c_char, n: usize) -> *mut c_char {
|
||||
let source = strerror_inner(e);
|
||||
strncpy(buf, source, n)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strncat(dst: *mut c_char, src: *const c_char, n: usize) -> *mut c_char {
|
||||
if dst.is_null() || src.is_null() {
|
||||
panic!();
|
||||
}
|
||||
let len = strnlen(src, n);
|
||||
let ptr = dst.add(strlen(dst));
|
||||
let ptr = mempcpy(ptr as _, src as _, len) as *mut c_char;
|
||||
*ptr = 0;
|
||||
|
||||
dst
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strncmp(mut a: *const c_char, mut b: *const c_char, mut n: usize) -> c_int {
|
||||
if a.is_null() {
|
||||
panic!();
|
||||
}
|
||||
if b.is_null() {
|
||||
panic!();
|
||||
}
|
||||
if a == b {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while n != 0 {
|
||||
match Ord::cmp(&*a, &*b) {
|
||||
Ordering::Less => return -1,
|
||||
Ordering::Greater => return 1,
|
||||
Ordering::Equal => (),
|
||||
}
|
||||
|
||||
if *a == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
a = a.add(1);
|
||||
b = b.add(1);
|
||||
n -= 1;
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strncpy(dst: *mut c_char, src: *const c_char, n: usize) -> *mut c_char {
|
||||
stpncpy(dst, src, n);
|
||||
dst
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strndup(s: *const c_char, n: usize) -> *mut c_char {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strnlen(s: *const c_char, n: usize) -> usize {
|
||||
if s.is_null() {
|
||||
panic!();
|
||||
}
|
||||
for i in 0..n {
|
||||
if *s.add(i) == 0 {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
n
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strpbrk(mut a: *const c_char, b: *const c_char) -> *mut c_char {
|
||||
if a.is_null() || b.is_null() {
|
||||
return null_mut();
|
||||
}
|
||||
|
||||
loop {
|
||||
let c = *a;
|
||||
|
||||
if c == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
if !strchr(b, c as _).is_null() {
|
||||
return a as _;
|
||||
}
|
||||
|
||||
a = a.add(1);
|
||||
}
|
||||
|
||||
null_mut()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strrchr(a: *const c_char, c: c_int) -> *mut c_char {
|
||||
if a.is_null() {
|
||||
return null_mut();
|
||||
}
|
||||
|
||||
let n = strnlen(a, usize::MAX);
|
||||
for i in (0..n).rev() {
|
||||
if *a.add(i) == c as _ {
|
||||
return a.add(i) as _;
|
||||
}
|
||||
}
|
||||
|
||||
null_mut()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strsignal(signum: c_int) -> *mut c_char {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strspn(mut s: *const c_char, accept: *const c_char) -> usize {
|
||||
if s.is_null() || accept.is_null() {
|
||||
panic!();
|
||||
}
|
||||
let mut n = 0;
|
||||
while *s != 0 {
|
||||
if strchr(accept, *s as _).is_null() {
|
||||
return n;
|
||||
}
|
||||
n += 1;
|
||||
s = s.add(1);
|
||||
}
|
||||
n
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strstr(mut a: *const c_char, b: *const c_char) -> *mut c_char {
|
||||
if a.is_null() || b.is_null() {
|
||||
panic!();
|
||||
}
|
||||
let n = strnlen(b, usize::MAX);
|
||||
if *a == 0 && *b == 0 {
|
||||
return a as _;
|
||||
}
|
||||
|
||||
while *a != 0 {
|
||||
if strncmp(a, b, n) == 0 {
|
||||
return a as _;
|
||||
}
|
||||
a = a.add(1);
|
||||
}
|
||||
|
||||
null_mut()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strtok(str: *mut c_char, delim: *const c_char) -> *mut c_char {
|
||||
static mut STRTOK_BUF: *mut c_char = null_mut();
|
||||
if !str.is_null() {
|
||||
STRTOK_BUF = null_mut();
|
||||
}
|
||||
strtok_r(str, delim, &raw mut STRTOK_BUF)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strtok_r(
|
||||
mut str: *mut c_char,
|
||||
delim: *const c_char,
|
||||
saveptr: *mut *mut c_char,
|
||||
) -> *mut c_char {
|
||||
if saveptr.is_null() || delim.is_null() {
|
||||
panic!();
|
||||
}
|
||||
|
||||
if str.is_null() {
|
||||
str = *saveptr;
|
||||
}
|
||||
|
||||
str = str.add(strspn(str, delim));
|
||||
|
||||
if *str == 0 {
|
||||
*saveptr = null_mut();
|
||||
return null_mut();
|
||||
}
|
||||
|
||||
let len = strcspn(str, delim);
|
||||
if *str.add(len) != 0 {
|
||||
*saveptr = str.add(len + 1);
|
||||
} else {
|
||||
*saveptr = null_mut();
|
||||
}
|
||||
*str.add(len) = 0;
|
||||
str as _
|
||||
}
|
||||
|
||||
// TODO locales
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strcoll(a: *const c_char, b: *const c_char) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strcoll_l(a: *const c_char, b: *const c_char, l: locale_t) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strerror_l(e: c_int, l: locale_t) -> *mut c_char {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strxfrm(a: *mut c_char, b: *const c_char, n: usize) -> usize {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strxfrm_l(a: *mut c_char, b: *const c_char, n: usize, l: locale_t) -> usize {
|
||||
todo!()
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
language = "C"
|
||||
style = "Type"
|
||||
|
||||
sys_includes = ["stddef.h"]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_STRINGS_H"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
exclude = []
|
||||
@@ -0,0 +1,29 @@
|
||||
use core::{
|
||||
cmp::Ordering,
|
||||
ffi::{c_char, c_int},
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_int {
|
||||
strncasecmp(s1, s2, usize::MAX)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strncasecmp(s1: *const c_char, s2: *const c_char, n: usize) -> c_int {
|
||||
for i in 0..n {
|
||||
let c0 = (*s1.add(i) as u8).to_ascii_lowercase();
|
||||
let c1 = (*s2.add(i) as u8).to_ascii_lowercase();
|
||||
|
||||
match c0.cmp(&c1) {
|
||||
Ordering::Less => return -1,
|
||||
Ordering::Equal => (),
|
||||
Ordering::Greater => return 1,
|
||||
}
|
||||
|
||||
if c0 == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
use core::{
|
||||
ops::{Deref, DerefMut},
|
||||
ptr::{null_mut, NonNull},
|
||||
fmt, ops::{Deref, DerefMut}, ptr::{null_mut, NonNull}
|
||||
};
|
||||
|
||||
use alloc::{boxed::Box, collections::btree_set::BTreeSet};
|
||||
@@ -331,6 +330,12 @@ impl FileOpenSource for &Path {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Write for FILE {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
self.write_all(s.as_bytes()).into_result(|_| fmt::Error, true)
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub static mut stdout: *mut FILE = null_mut();
|
||||
#[no_mangle]
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use core::{ffi::c_int, time::Duration};
|
||||
use core::{ffi::{c_char, c_int, CStr}, ptr::NonNull, time::Duration};
|
||||
|
||||
use yggdrasil_rt::{process::ExitCode, sys as syscall};
|
||||
|
||||
use crate::{error::EResult, headers::sys_types::pid_t, io};
|
||||
use crate::{error::EResult, headers::sys_types::pid_t, io::{self, managed::stderr}};
|
||||
|
||||
pub fn getpid() -> pid_t {
|
||||
let pid = unsafe { syscall::get_pid() };
|
||||
@@ -19,6 +19,10 @@ pub fn sleep(duration: Duration) -> EResult<()> {
|
||||
EResult::Ok(())
|
||||
}
|
||||
|
||||
pub fn abort() -> ! {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn c_exit_immediately(status: c_int) -> ! {
|
||||
let code = ExitCode::Exited(status);
|
||||
unsafe { syscall::exit_process(code) };
|
||||
@@ -34,3 +38,22 @@ pub fn c_exit(status: c_int) -> ! {
|
||||
unsafe fn pre_exit() {
|
||||
io::cleanup();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn __assert_fail(file: *const c_char, line: c_int, message: *const c_char) -> ! {
|
||||
use core::fmt::Write;
|
||||
|
||||
let err = stderr.as_mut().unwrap();
|
||||
let file = match file.is_null() {
|
||||
false => CStr::from_ptr(file).to_str().ok(),
|
||||
true => None
|
||||
}.unwrap_or("???");
|
||||
let expr = match message.is_null() {
|
||||
false => CStr::from_ptr(message).to_str().ok(),
|
||||
true => None
|
||||
}.unwrap_or("???");
|
||||
|
||||
writeln!(err, "Assertion failed: '{}' at {}:{}", expr, file, line).ok();
|
||||
|
||||
abort()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
use std::{path::PathBuf, process::Command};
|
||||
|
||||
use crate::{env::BuildEnv, error::Error};
|
||||
|
||||
pub struct Llvm {
|
||||
root: PathBuf,
|
||||
}
|
||||
|
||||
impl Llvm {
|
||||
pub fn c_clang(&self, env: &BuildEnv) -> Command {
|
||||
let mut command = Command::new(self.root.join("bin/clang"));
|
||||
command.arg(format!("--target={}-unknown-yggdrasil", env.arch.name()));
|
||||
command.arg(format!("--sysroot={}", env.llvm_sysroot.display()));
|
||||
command
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_llvm(env: &BuildEnv) -> Result<Llvm, Error> {
|
||||
// TODO actually build and install LLVM
|
||||
Ok(Llvm {
|
||||
root: env.workspace_root.join("toolchain-c/prefix/host"),
|
||||
})
|
||||
}
|
||||
@@ -14,6 +14,7 @@ pub mod i686;
|
||||
pub mod x86_64;
|
||||
|
||||
mod cargo;
|
||||
pub mod llvm;
|
||||
mod module;
|
||||
pub mod toolchain;
|
||||
mod userspace;
|
||||
|
||||
@@ -2,20 +2,24 @@ use std::{
|
||||
fs::{self, File},
|
||||
io::BufWriter,
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
};
|
||||
|
||||
use walkdir::WalkDir;
|
||||
|
||||
use crate::{
|
||||
build::cargo::CargoBuilder,
|
||||
build::{cargo::CargoBuilder, llvm},
|
||||
check::AllOk,
|
||||
env::{Arch, BuildEnv},
|
||||
env::BuildEnv,
|
||||
error::Error,
|
||||
util,
|
||||
};
|
||||
|
||||
use super::InitrdGenerated;
|
||||
use super::{llvm::Llvm, InitrdGenerated};
|
||||
|
||||
pub struct Ygglibc {
|
||||
lib_file: PathBuf,
|
||||
include_paths: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
const PROGRAMS: &[(&str, &str)] = &[
|
||||
// init
|
||||
@@ -66,36 +70,15 @@ const PROGRAMS: &[(&str, &str)] = &[
|
||||
("c-test", "c-test"),
|
||||
];
|
||||
|
||||
fn build_test_c_program(env: &BuildEnv) -> Result<(), Error> {
|
||||
fn build_test_c_program(env: &BuildEnv, llvm: &Llvm) -> Result<(), Error> {
|
||||
log::info!("Building a test C program");
|
||||
let mut command = Command::new("clang");
|
||||
match env.arch {
|
||||
Arch::aarch64 => todo!(),
|
||||
Arch::i686 => todo!(),
|
||||
Arch::x86_64 => {
|
||||
command.args(["-target", "x86_64-unknown-none"]);
|
||||
}
|
||||
}
|
||||
|
||||
let ygglibc_target = format!("{:?}-unknown-none", env.arch);
|
||||
let ygglibc_target_dir = env
|
||||
.workspace_root
|
||||
.join("userspace/lib/ygglibc/target")
|
||||
.join(ygglibc_target)
|
||||
.join(env.profile.dir());
|
||||
let target_dir = &env.userspace_output_dir;
|
||||
|
||||
let mut command = llvm.c_clang(env);
|
||||
command
|
||||
.args(["-nostdlib", "-ffreestanding", "-static", "-Og", "-ggdb"])
|
||||
.arg("-I")
|
||||
.arg("userspace/lib/ygglibc/include")
|
||||
.arg("-I")
|
||||
.arg(ygglibc_target_dir.join("include"))
|
||||
.args(["-static", "-Og", "-ggdb"])
|
||||
.arg("-o")
|
||||
.arg(target_dir.join("c-test"))
|
||||
.arg(ygglibc_target_dir.join("libygglibc.a"))
|
||||
.arg(env.workspace_root.join("test.c"))
|
||||
.arg(ygglibc_target_dir.join("libygglibc.a"));
|
||||
.arg(env.workspace_root.join("test.c"));
|
||||
|
||||
if !command.status()?.success() {
|
||||
return Err(Error::ExternalCommandFailed);
|
||||
@@ -104,12 +87,52 @@ fn build_test_c_program(env: &BuildEnv) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn install_ygglibc(env: &BuildEnv, ygglibc: Ygglibc) -> Result<(), Error> {
|
||||
log::info!("Installing ygglibc into LLVM sysroot");
|
||||
|
||||
let dst_lib_dir = env.llvm_sysroot.join("lib");
|
||||
let dst_include_dir = env.llvm_sysroot.join("usr/include");
|
||||
|
||||
fs::create_dir_all(&dst_lib_dir)?;
|
||||
fs::create_dir_all(&dst_include_dir)?;
|
||||
|
||||
fs::copy(ygglibc.lib_file, dst_lib_dir.join("libygglibc.a"))?;
|
||||
|
||||
for path in ygglibc.include_paths {
|
||||
util::copy_dir_recursive(&path, &dst_include_dir)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build_ygglibc(env: &BuildEnv) -> Result<Ygglibc, Error> {
|
||||
let ygglibc_dir = env.workspace_root.join("userspace/lib/ygglibc");
|
||||
let target_dir = ygglibc_dir.join(format!(
|
||||
"target/{}-unknown-none/{}",
|
||||
env.arch.name(),
|
||||
env.profile.dir()
|
||||
));
|
||||
CargoBuilder::Ygglibc(env).build(&ygglibc_dir)?;
|
||||
let lib_file = target_dir.join("libygglibc.a");
|
||||
let generated_includes = target_dir.join("include");
|
||||
let static_includes = ygglibc_dir.join("include");
|
||||
|
||||
Ok(Ygglibc {
|
||||
lib_file,
|
||||
include_paths: vec![generated_includes, static_includes],
|
||||
})
|
||||
}
|
||||
|
||||
fn build_userspace(env: &BuildEnv, _: AllOk) -> Result<(), Error> {
|
||||
log::info!("Building userspace");
|
||||
CargoBuilder::Userspace(env).build(env.workspace_root.join("userspace"))?;
|
||||
CargoBuilder::Userspace(env).build(env.workspace_root.join("userspace/dynload-program"))?;
|
||||
CargoBuilder::Ygglibc(env).build(env.workspace_root.join("userspace/lib/ygglibc"))?;
|
||||
build_test_c_program(env)?;
|
||||
|
||||
let ygglibc = build_ygglibc(env)?;
|
||||
let llvm = llvm::build_llvm(env)?;
|
||||
install_ygglibc(env, ygglibc)?;
|
||||
build_test_c_program(env, &llvm)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
+12
-3
@@ -28,7 +28,7 @@ pub enum Arch {
|
||||
#[default]
|
||||
aarch64,
|
||||
x86_64,
|
||||
i686
|
||||
i686,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -45,6 +45,8 @@ pub struct BuildEnv {
|
||||
pub kernel_output_dir: PathBuf,
|
||||
pub userspace_output_dir: PathBuf,
|
||||
pub kernel_symbol_file: PathBuf,
|
||||
|
||||
pub llvm_sysroot: PathBuf,
|
||||
}
|
||||
|
||||
impl Default for ToolchainConfig {
|
||||
@@ -73,6 +75,11 @@ impl BuildEnv {
|
||||
let kernel_symbol_file = kernel_output_dir.join("symbols.dat");
|
||||
let host = env!("TARGET");
|
||||
|
||||
let llvm_sysroot = workspace_root.join(format!(
|
||||
"toolchain-c/sysroot/{}-unknown-yggdrasil",
|
||||
arch.name()
|
||||
));
|
||||
|
||||
Self {
|
||||
config,
|
||||
verbose,
|
||||
@@ -86,6 +93,8 @@ impl BuildEnv {
|
||||
kernel_symbol_file,
|
||||
kernel_output_dir,
|
||||
userspace_output_dir,
|
||||
|
||||
llvm_sysroot,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,7 +117,7 @@ impl Arch {
|
||||
match self {
|
||||
Self::aarch64 => "aarch64-unknown-qemu",
|
||||
Self::x86_64 => "x86_64-unknown-none",
|
||||
Self::i686 => "i686-unknown-none"
|
||||
Self::i686 => "i686-unknown-none",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +125,7 @@ impl Arch {
|
||||
match self {
|
||||
Self::aarch64 => "aarch64-unknown-yggdrasil",
|
||||
Self::x86_64 => "x86_64-unknown-yggdrasil",
|
||||
Self::i686 => "i686-unknown-yggdrasil"
|
||||
Self::i686 => "i686-unknown-yggdrasil",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user