From 3a923aa62d168d05c45d02c8e53804d7fdfe7f05 Mon Sep 17 00:00:00 2001 From: oddcoder Date: Fri, 24 Apr 2020 15:39:08 +0200 Subject: [PATCH 01/13] Implement #include and #include This patch implements sys/user.h file that works for both x86_64 as well as aarch64. This include file is used by sys/procfs.h which is needed dependency for binutils. There is bug in this patch in aarch64 implementation which is the lack of f128 implementation in rust, thus we can't create cbinding for long double. --- include/sys/user.h | 11 +++ src/header/arch_aarch64_user/cbindgen.toml | 7 ++ src/header/arch_aarch64_user/mod.rs | 30 ++++++++ .../{sys_user => arch_x64_user}/cbindgen.toml | 2 +- src/header/{sys_user => arch_x64_user}/mod.rs | 29 +++++++- src/header/mod.rs | 4 +- src/header/sys_procfs/cbindgen.toml | 7 ++ src/header/sys_procfs/mod.rs | 73 +++++++++++++++++++ 8 files changed, 160 insertions(+), 3 deletions(-) create mode 100644 include/sys/user.h create mode 100644 src/header/arch_aarch64_user/cbindgen.toml create mode 100644 src/header/arch_aarch64_user/mod.rs rename src/header/{sys_user => arch_x64_user}/cbindgen.toml (72%) rename src/header/{sys_user => arch_x64_user}/mod.rs (61%) create mode 100644 src/header/sys_procfs/cbindgen.toml create mode 100644 src/header/sys_procfs/mod.rs diff --git a/include/sys/user.h b/include/sys/user.h new file mode 100644 index 0000000000..cc0333a628 --- /dev/null +++ b/include/sys/user.h @@ -0,0 +1,11 @@ +#ifndef _SYS_USER_H +#define _SYS_USER_H +#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64) +#include +#elif defined(__aarch64__) +#include +#else +#error "Unknown architecture" +#endif + +#endif \ No newline at end of file diff --git a/src/header/arch_aarch64_user/cbindgen.toml b/src/header/arch_aarch64_user/cbindgen.toml new file mode 100644 index 0000000000..2000868e87 --- /dev/null +++ b/src/header/arch_aarch64_user/cbindgen.toml @@ -0,0 +1,7 @@ +sys_includes = [] +include_guard = "_AARCH64_USER_H" +language = "C" +style = "Tag" + +[enum] +prefix_with_name = true diff --git a/src/header/arch_aarch64_user/mod.rs b/src/header/arch_aarch64_user/mod.rs new file mode 100644 index 0000000000..6f25a5da80 --- /dev/null +++ b/src/header/arch_aarch64_user/mod.rs @@ -0,0 +1,30 @@ +use crate::platform::types::*; + +#[repr(C)] +pub struct user_regs_struct { + pub regs: [c_ulonglong; 31], + pub sp: c_ulonglong, + pub pc: c_ulonglong, + pub pstate: c_ulonglong, +} + +#[repr(C)] +pub struct user_fpsimd_struct { + pub vregs: [c_double; 32], // BUG: rust doesn't have f128 which is equivalent for long double + pub fpsr: c_uint, + pub fpcr: c_uint, +} + +pub type elf_greg_t = c_ulong; +pub type elf_gregset_t = [c_ulong; 34]; +pub type elf_fpregset_t = user_fpsimd_struct; + +#[no_mangle] +pub extern "C" fn _cbindgen_only_generates_structs_if_they_are_mentioned_which_is_dumb_aarch64_user( + a: user_regs_struct, + b: user_fpsimd_struct, + c: elf_gregset_t, + d: elf_greg_t, + e: elf_fpregset_t, +) { +} diff --git a/src/header/sys_user/cbindgen.toml b/src/header/arch_x64_user/cbindgen.toml similarity index 72% rename from src/header/sys_user/cbindgen.toml rename to src/header/arch_x64_user/cbindgen.toml index 63c05e2adc..04a2ccea4e 100644 --- a/src/header/sys_user/cbindgen.toml +++ b/src/header/arch_x64_user/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = [] -include_guard = "_SYS_USER_H" +include_guard = "_X64_USER_H" language = "C" style = "Tag" diff --git a/src/header/sys_user/mod.rs b/src/header/arch_x64_user/mod.rs similarity index 61% rename from src/header/sys_user/mod.rs rename to src/header/arch_x64_user/mod.rs index 37ef15544f..92d34b6279 100644 --- a/src/header/sys_user/mod.rs +++ b/src/header/arch_x64_user/mod.rs @@ -48,9 +48,36 @@ pub struct user_regs_struct { pub gs: c_ulong, } +pub type elf_greg_t = c_ulong; + +pub type elf_gregset_t = [c_ulong; 27]; +pub type elf_fpregset_t = user_fpregs_struct; +#[repr(C)] +pub struct user { + pub regs: user_regs_struct, + pub u_fpvalid: c_int, + pub i387: user_fpregs_struct, + pub u_tsize: c_ulong, + pub u_dsize: c_ulong, + pub u_ssize: c_ulong, + pub start_code: c_ulong, + pub start_stack: c_ulong, + pub signal: c_long, + pub reserved: c_int, + pub u_ar0: *mut user_regs_struct, + pub u_fpstate: *mut user_fpregs_struct, + pub magic: c_ulong, + pub u_comm: [c_char; 32], + pub u_debugreg: [c_ulong; 8], +} + #[no_mangle] -pub extern "C" fn _cbindgen_only_generates_structs_if_they_are_mentioned_which_is_dumb( +pub extern "C" fn _cbindgen_only_generates_structs_if_they_are_mentioned_which_is_dumb_x86_user( a: user_fpregs_struct, b: user_regs_struct, + c: user, + d: elf_gregset_t, + e: elf_greg_t, + f: elf_fpregset_t, ) { } diff --git a/src/header/mod.rs b/src/header/mod.rs index 80da6f4214..c6167c59bb 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -47,9 +47,11 @@ pub mod sys_time; pub mod sys_timeb; //pub mod sys_times; pub mod _wctype; +pub mod arch_aarch64_user; +pub mod arch_x64_user; +pub mod sys_procfs; pub mod sys_uio; pub mod sys_un; -pub mod sys_user; pub mod sys_utsname; pub mod sys_wait; pub mod termios; diff --git a/src/header/sys_procfs/cbindgen.toml b/src/header/sys_procfs/cbindgen.toml new file mode 100644 index 0000000000..9328ff99d3 --- /dev/null +++ b/src/header/sys_procfs/cbindgen.toml @@ -0,0 +1,7 @@ +sys_includes = ["sys/user.h"] +include_guard = "_SYS_PROCFS_H" +language = "C" +style = "Tag" + +[enum] +prefix_with_name = true diff --git a/src/header/sys_procfs/mod.rs b/src/header/sys_procfs/mod.rs new file mode 100644 index 0000000000..a70aa9f6c1 --- /dev/null +++ b/src/header/sys_procfs/mod.rs @@ -0,0 +1,73 @@ +#[cfg(target_arch = "aarch64")] +use crate::header::arch_aarch64_user::*; +#[cfg(target_arch = "x86_64")] +use crate::header::arch_x64_user::*; +use crate::platform::types::*; + +pub const ELF_PRARGSZ: size_t = 80; + +#[repr(C)] +pub struct elf_siginfo { + pub si_signo: c_int, + pub si_code: c_int, + pub si_errno: c_int, +} + +#[repr(C)] +pub struct time { + pub tv_sec: c_long, + pub tv_usec: c_long, +} + +#[repr(C)] +pub struct elf_prstatus { + pub pr_info: elf_siginfo, + pub pr_cursig: c_short, + pub pr_sigpend: c_ulong, + pub pr_sighold: c_ulong, + pub pr_pid: pid_t, + pub pr_ppid: pid_t, + pub pr_pgrp: pid_t, + pub pr_sid: pid_t, + pub pr_utime: time, + pub pr_stime: time, + pub pr_cutime: time, + pub pr_cstime: time, + pub pr_reg: elf_gregset_t, + pub pr_fpvalid: c_int, +} + +#[repr(C)] +pub struct elf_prpsinfo { + pub pr_state: c_char, + pub pr_sname: c_char, + pub pr_zomb: c_char, + pub pr_nice: c_char, + pub pr_flag: c_uint, + pub pr_uid: c_uint, + pub pr_gid: c_uint, + pub pr_pid: c_int, + pub pr_ppid: c_int, + pub pr_pgrp: c_int, + pub pr_sid: c_int, + pub pr_fname: [c_char; 16], + pub pr_psargs: [c_char; ELF_PRARGSZ], +} + +pub type psaddr_t = *mut c_void; +pub type prgregset_t = elf_gregset_t; +pub type prfpregset_t = elf_fpregset_t; +pub type lwpid_t = pid_t; +pub type prstatus_t = elf_prstatus; +pub type prpsinfo_t = elf_prpsinfo; + +#[no_mangle] +pub extern "C" fn _cbindgen_only_generates_structs_if_they_are_mentioned_which_is_dumb_procfs( + a: psaddr_t, + b: prgregset_t, + c: prfpregset_t, + d: lwpid_t, + e: prstatus_t, + f: prpsinfo_t, +) { +} From 162999ac0baa7e9a2d8bdd762a470e00f339838d Mon Sep 17 00:00:00 2001 From: oddcoder Date: Sun, 26 Apr 2020 12:38:20 +0200 Subject: [PATCH 02/13] Move towlower and towupper to wctype.h and Implement it This patch creates wctype.h and impelementat two functions that belong to that header file towupper and towlower. These functions are building blocks for wcscasecmp and wcsncasecmp which are utilized by binutils. The implementation for towlower and towupper seams to be complex so this implementation is mimicking that of musl libc --- src/header/mod.rs | 1 + src/header/wchar/mod.rs | 19 +- src/header/wctype/casecmp.rs | 406 ++++++++++++++++++++++++++++++++ src/header/wctype/cbindgen.toml | 10 + src/header/wctype/mod.rs | 17 ++ 5 files changed, 438 insertions(+), 15 deletions(-) create mode 100644 src/header/wctype/casecmp.rs create mode 100644 src/header/wctype/cbindgen.toml create mode 100644 src/header/wctype/mod.rs diff --git a/src/header/mod.rs b/src/header/mod.rs index c6167c59bb..2de1178582 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -59,3 +59,4 @@ pub mod time; pub mod unistd; pub mod utime; pub mod wchar; +pub mod wctype; diff --git a/src/header/wchar/mod.rs b/src/header/wchar/mod.rs index 8d63325f9c..ad371d8c68 100644 --- a/src/header/wchar/mod.rs +++ b/src/header/wchar/mod.rs @@ -3,14 +3,13 @@ use core::{char, ffi::VaList as va_list, mem, ptr, slice, usize}; use crate::{ - header::{ctype::isspace, errno::ERANGE, stdio::*, stdlib::MB_CUR_MAX, string, time::*}, + header::{ + ctype::isspace, errno::ERANGE, stdio::*, stdlib::MB_CUR_MAX, string, time::*, wctype::*, + }, platform::{self, types::*}, }; mod utf8; - -const WEOF: wint_t = 0xFFFF_FFFFu32; - #[repr(C)] #[derive(Clone, Copy)] pub struct mbstate_t; @@ -27,7 +26,7 @@ pub unsafe extern "C" fn btowc(c: c_int) -> wint_t { let mut ps: mbstate_t = mbstate_t; let mut wc: wchar_t = 0; let saved_errno = platform::errno; - let status = mbrtowc(&mut wc, &c as (*const c_char), 1, &mut ps); + let status = mbrtowc(&mut wc, &c as *const c_char, 1, &mut ps); if status == usize::max_value() || status == usize::max_value() - 1 { platform::errno = saved_errno; return WEOF; @@ -238,16 +237,6 @@ pub extern "C" fn swscanf(s: *const wchar_t, format: *const wchar_t, ap: va_list unimplemented!(); } -// #[no_mangle] -pub extern "C" fn towlower(wc: wint_t) -> wint_t { - unimplemented!(); -} - -// #[no_mangle] -pub extern "C" fn towupper(wc: wint_t) -> wint_t { - unimplemented!(); -} - // #[no_mangle] pub extern "C" fn ungetwc(wc: wint_t, stream: *mut FILE) -> wint_t { unimplemented!(); diff --git a/src/header/wctype/casecmp.rs b/src/header/wctype/casecmp.rs new file mode 100644 index 0000000000..a15e9292f6 --- /dev/null +++ b/src/header/wctype/casecmp.rs @@ -0,0 +1,406 @@ +use crate::platform::types::*; +const tab: [c_uchar; 2666] = [ + 7, 8, 9, 10, 11, 12, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 13, 6, 6, 14, 6, 6, 6, 6, 6, 6, 6, 6, 15, + 16, 17, 18, 6, 19, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 20, 21, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 22, 23, 6, 6, 6, 24, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 25, 6, 6, 6, 6, 26, 6, 6, 6, 6, 6, 6, 6, 27, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 28, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 29, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 30, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 43, 43, 43, + 43, 43, 43, 43, 43, 1, 0, 84, 86, 86, 86, 86, 86, 86, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 43, 43, 43, 43, 43, 43, 43, 7, 43, 43, 91, 86, 86, 86, 86, + 86, 86, 86, 74, 86, 86, 5, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 36, + 80, 121, 49, 80, 49, 80, 49, 56, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, + 78, 49, 2, 78, 13, 13, 78, 3, 78, 0, 36, 110, 0, 78, 49, 38, 110, 81, 78, 36, 80, 78, 57, 20, + 129, 27, 29, 29, 83, 49, 80, 49, 80, 13, 49, 80, 49, 80, 49, 80, 27, 83, 36, 80, 49, 2, 92, + 123, 92, 123, 92, 123, 92, 123, 92, 123, 20, 121, 92, 123, 92, 123, 92, 45, 43, 73, 3, 72, 3, + 120, 92, 123, 20, 0, 150, 10, 1, 43, 40, 6, 6, 0, 42, 6, 42, 42, 43, 7, 187, 181, 43, 30, 0, + 43, 7, 43, 43, 43, 1, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 1, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 205, 70, 205, 43, 0, 37, 43, 7, 1, 6, 1, 85, 86, 86, 86, 86, 86, 85, 86, 86, 2, + 36, 129, 129, 129, 129, 129, 21, 129, 129, 129, 0, 0, 43, 0, 178, 209, 178, 209, 178, 209, 178, + 209, 0, 0, 205, 204, 1, 0, 215, 215, 215, 215, 215, 131, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 28, 0, 0, 0, 0, 0, 49, 80, 49, + 80, 49, 80, 49, 80, 49, 80, 49, 2, 0, 0, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, + 80, 49, 80, 49, 80, 78, 49, 80, 49, 80, 78, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, + 80, 49, 2, 135, 166, 135, 166, 135, 166, 135, 166, 135, 166, 135, 166, 135, 166, 135, 166, 42, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 0, 0, 0, 84, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 84, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 12, 0, 12, 42, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 7, 42, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 86, 86, 108, 129, 21, 0, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 7, 108, 3, 65, 43, 43, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 44, 86, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 108, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 37, 6, + 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, + 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 86, 122, 158, 38, 6, 37, + 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, 37, 6, + 37, 6, 1, 43, 43, 79, 86, 86, 44, 43, 127, 86, 86, 57, 43, 43, 85, 86, 86, 43, 43, 79, 86, 86, + 44, 43, 127, 86, 86, 129, 55, 117, 91, 123, 92, 43, 43, 79, 86, 86, 2, 172, 4, 0, 0, 57, 43, + 43, 85, 86, 86, 43, 43, 79, 86, 86, 44, 43, 43, 86, 86, 50, 19, 129, 87, 0, 111, 129, 126, 201, + 215, 126, 45, 129, 129, 14, 126, 57, 127, 111, 87, 0, 129, 129, 126, 21, 0, 126, 3, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 7, 43, 36, 43, 151, 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, + 43, 43, 43, 43, 43, 86, 86, 86, 86, 86, 128, 129, 129, 129, 129, 57, 187, 42, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 1, 129, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 201, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 208, 13, 0, 78, 49, 2, 180, 193, 193, 215, 215, 36, 80, 49, 80, 49, 80, 49, 80, + 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, + 49, 80, 215, 215, 83, 193, 71, 212, 215, 215, 215, 5, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 7, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 78, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 49, 80, 13, 0, 0, 0, 0, 0, 36, 80, + 49, 80, 49, 80, 49, 80, 49, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 121, 92, + 123, 92, 123, 79, 123, 92, 123, 92, 123, 92, 123, 92, 123, 92, 123, 92, 123, 92, 123, 92, 123, + 92, 123, 92, 45, 43, 43, 121, 20, 92, 123, 92, 45, 121, 42, 92, 39, 92, 123, 92, 123, 92, 123, + 164, 0, 10, 180, 92, 123, 92, 123, 79, 3, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 43, 43, 43, 43, 43, 43, 43, 7, + 0, 72, 86, 86, 86, 86, 86, 86, 86, 86, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 85, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 7, 0, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 7, 0, 0, 0, 0, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 85, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +]; +const rules: [c_int; 240] = [ + 0x0, 0x2001, -0x2000, 0x1dbf00, 0x2e700, 0x7900, 0x2402, 0x101, -0x100, 0x0, 0x201, -0x200, + -0xc6ff, -0xe800, -0x78ff, -0x12c00, 0xc300, 0xd201, 0xce01, 0xcd01, 0x4f01, 0xca01, 0xcb01, + 0xcf01, 0x6100, 0xd301, 0xd101, 0xa300, 0xd501, 0x8200, 0xd601, 0xda01, 0xd901, 0xdb01, 0x3800, + 0x3, -0x4f00, -0x60ff, -0x37ff, 0x242802, 0x0, 0x101, -0x100, -0xcd00, -0xda00, -0x81ff, + 0x2a2b01, -0xa2ff, 0x2a2801, 0x2a3f00, -0xc2ff, 0x4501, 0x4701, 0x2a1f00, 0x2a1c00, 0x2a1e00, + -0xd200, -0xce00, -0xca00, -0xcb00, 0xa54f00, 0xa54b00, -0xcf00, 0xa52800, 0xa54400, -0xd100, + -0xd300, 0x29f700, 0xa54100, 0x29fd00, -0xd500, -0xd600, 0x29e700, 0xa54300, 0xa52a00, -0x4500, + -0xd900, -0x4700, -0xdb00, 0xa51500, 0xa51200, 0x4c2402, 0x0, 0x2001, -0x2000, 0x101, -0x100, + 0x5400, 0x7401, 0x2601, 0x2501, 0x4001, 0x3f01, -0x2600, -0x2500, -0x1f00, -0x4000, -0x3f00, + 0x801, -0x3e00, -0x3900, -0x2f00, -0x3600, -0x800, -0x5600, -0x5000, 0x700, -0x7400, -0x3bff, + -0x6000, -0x6ff, 0x701a02, 0x101, -0x100, 0x2001, -0x2000, 0x5001, 0xf01, -0xf00, 0x0, 0x3001, + -0x3000, 0x101, -0x100, 0x0, 0xbc000, 0x1c6001, 0x0, 0x97d001, 0x801, -0x800, 0x8a0502, 0x0, + -0xbbfff, -0x186200, 0x89c200, -0x182500, -0x186e00, -0x186d00, -0x186400, -0x186300, + -0x185c00, 0x0, 0x8a3800, 0x8a0400, 0xee600, 0x101, -0x100, 0x0, -0x3b00, -0x1dbeff, 0x8f1d02, + 0x800, -0x7ff, 0x0, 0x5600, -0x55ff, 0x4a00, 0x6400, 0x8000, 0x7000, 0x7e00, 0x900, -0x49ff, + -0x8ff, -0x1c2500, -0x63ff, -0x6fff, -0x7fff, -0x7dff, 0xac0502, 0x0, 0x1001, -0x1000, 0x1c01, + 0x101, -0x1d5cff, -0x20beff, -0x2045ff, -0x1c00, 0xb10b02, 0x101, -0x100, 0x3001, -0x3000, 0x0, + -0x29f6ff, -0xee5ff, -0x29e6ff, -0x2a2b00, -0x2a2800, -0x2a1bff, -0x29fcff, -0x2a1eff, + -0x2a1dff, -0x2a3eff, 0x0, -0x1c6000, 0x0, 0x101, -0x100, 0xbc0c02, 0x0, 0x101, -0x100, + -0xa543ff, 0x3a001, -0x8a03ff, -0xa527ff, 0x3000, -0xa54eff, -0xa54aff, -0xa540ff, -0xa511ff, + -0xa529ff, -0xa514ff, -0x2fff, -0xa542ff, -0x8a37ff, 0x0, -0x97d000, -0x3a000, 0x0, 0x2001, + -0x2000, 0x0, 0x2801, -0x2800, 0x0, 0x4001, -0x4000, 0x0, 0x2001, -0x2000, 0x0, 0x2001, + -0x2000, 0x0, 0x2201, -0x2200, +]; +const rulebases: [c_uchar; 512] = [ + 0, 6, 39, 81, 111, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, + 131, 142, 146, 151, 0, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 201, 0, 0, 0, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 0, 0, 0, 0, 225, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +]; +const exceptions: [[c_uchar; 2]; 200] = [ + [48, 12], + [49, 13], + [120, 14], + [127, 15], + [128, 16], + [129, 17], + [134, 18], + [137, 19], + [138, 19], + [142, 20], + [143, 21], + [144, 22], + [147, 19], + [148, 23], + [149, 24], + [150, 25], + [151, 26], + [154, 27], + [156, 25], + [157, 28], + [158, 29], + [159, 30], + [166, 31], + [169, 31], + [174, 31], + [177, 32], + [178, 32], + [183, 33], + [191, 34], + [197, 35], + [200, 35], + [203, 35], + [221, 36], + [242, 35], + [246, 37], + [247, 38], + [32, 45], + [58, 46], + [61, 47], + [62, 48], + [63, 49], + [64, 49], + [67, 50], + [68, 51], + [69, 52], + [80, 53], + [81, 54], + [82, 55], + [83, 56], + [84, 57], + [89, 58], + [91, 59], + [92, 60], + [97, 61], + [99, 62], + [101, 63], + [102, 64], + [104, 65], + [105, 66], + [106, 64], + [107, 67], + [108, 68], + [111, 66], + [113, 69], + [114, 70], + [117, 71], + [125, 72], + [130, 73], + [135, 74], + [137, 75], + [138, 76], + [139, 76], + [140, 77], + [146, 78], + [157, 79], + [158, 80], + [69, 87], + [123, 29], + [124, 29], + [125, 29], + [127, 88], + [134, 89], + [136, 90], + [137, 90], + [138, 90], + [140, 91], + [142, 92], + [143, 92], + [172, 93], + [173, 94], + [174, 94], + [175, 94], + [194, 95], + [204, 96], + [205, 97], + [206, 97], + [207, 98], + [208, 99], + [209, 100], + [213, 101], + [214, 102], + [215, 103], + [240, 104], + [241, 105], + [242, 106], + [243, 107], + [244, 108], + [245, 109], + [249, 110], + [253, 45], + [254, 45], + [255, 45], + [80, 105], + [81, 105], + [82, 105], + [83, 105], + [84, 105], + [85, 105], + [86, 105], + [87, 105], + [88, 105], + [89, 105], + [90, 105], + [91, 105], + [92, 105], + [93, 105], + [94, 105], + [95, 105], + [130, 0], + [131, 0], + [132, 0], + [133, 0], + [134, 0], + [135, 0], + [136, 0], + [137, 0], + [192, 117], + [207, 118], + [128, 137], + [129, 138], + [130, 139], + [133, 140], + [134, 141], + [112, 157], + [113, 157], + [118, 158], + [119, 158], + [120, 159], + [121, 159], + [122, 160], + [123, 160], + [124, 161], + [125, 161], + [179, 162], + [186, 163], + [187, 163], + [188, 164], + [190, 165], + [195, 162], + [204, 164], + [218, 166], + [219, 166], + [229, 106], + [234, 167], + [235, 167], + [236, 110], + [243, 162], + [248, 168], + [249, 168], + [250, 169], + [251, 169], + [252, 164], + [38, 176], + [42, 177], + [43, 178], + [78, 179], + [132, 8], + [98, 186], + [99, 187], + [100, 188], + [101, 189], + [102, 190], + [109, 191], + [110, 192], + [111, 193], + [112, 194], + [126, 195], + [127, 195], + [125, 207], + [141, 208], + [148, 209], + [171, 210], + [172, 211], + [173, 212], + [176, 213], + [177, 214], + [178, 215], + [196, 216], + [197, 217], + [198, 218], +]; + +pub fn casemap(mut c: u32, dir: i32) -> wint_t { + if c >= 0x20000 { + return c; + } + let c0 = c; + let b = c >> 8; + c &= 255; + let x = c / 3; + let y = c % 3; + /* lookup entry in two-level base-6 table */ + let mut v: c_uint = tab[(tab[b as usize] as u32 * 86 + x) as usize] as c_uint; + let mt: [c_uint; 3] = [2048, 342, 57]; + v = (v * mt[y as usize] >> 11) % 6; + + /* use the bit vector out of the tables as an index into + * a block-specific set of rules and decode the rule into + * a type and a case-mapping delta. */ + let mut r: c_int = rules[(rulebases[b as usize] as c_uint + v) as usize]; + let mut rt: c_uint = (r & 255) as c_uint; + let mut rd: c_int = r >> 8; + + /* rules 0/1 are simple lower/upper case with a delta. + * apply according to desired mapping direction. */ + if rt < 2 { + let tmp = -((rt ^ dir as c_uint) as c_int) as c_uint; + return c0.wrapping_add(rd as c_uint & tmp); + } + + /* binary search. endpoints of the binary search for + * this block are stored in the rule delta field. */ + let mut xn: c_uint = (rd & 0xff) as c_uint; + let mut xb: c_uint = rd as c_uint >> 8; + while xn != 0 { + let attempt: c_uint = exceptions[(xb + xn / 2) as usize][0] as c_uint; + if attempt == c { + r = rules[exceptions[(xb + xn / 2) as usize][1] as usize]; + rt = r as c_uint & 255; + rd = r >> 8; + if rt < 2 { + let tmp = -((rt ^ dir as c_uint) as c_int) as c_uint; + return c0.wrapping_add(rd as c_uint & tmp); + } + /* Hard-coded for the four exceptional titlecase */ + if dir == 0 { + return c0 + 1; + } else { + return c0 - 1; + } + } else if attempt > c { + xn /= 2; + } else { + xb += xn / 2; + xn -= xn / 2; + } + } + return c0; +} diff --git a/src/header/wctype/cbindgen.toml b/src/header/wctype/cbindgen.toml new file mode 100644 index 0000000000..3f2c4ff4db --- /dev/null +++ b/src/header/wctype/cbindgen.toml @@ -0,0 +1,10 @@ +sys_includes = ["stddef.h", "stdint.h", "time.h", "stdio.h" ] +include_guard = "_WCTYPE_H" +header = "" +language = "C" +style = "Type" +no_includes = true +cpp_compat = true + +[enum] +prefix_with_name = true diff --git a/src/header/wctype/mod.rs b/src/header/wctype/mod.rs new file mode 100644 index 0000000000..b4b7b0eaa9 --- /dev/null +++ b/src/header/wctype/mod.rs @@ -0,0 +1,17 @@ +//! wchar implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/wchar.h.html + +use crate::platform::types::*; + +mod casecmp; +use casecmp::casemap; +pub const WEOF: wint_t = 0xFFFF_FFFFu32; + +#[no_mangle] +pub extern "C" fn towlower(wc: wint_t) -> wint_t { + casemap(wc, 0) +} + +#[no_mangle] +pub extern "C" fn towupper(wc: wint_t) -> wint_t { + casemap(wc, 1) +} From 9725d3418af87be960cba46f1c957b24e9d69550 Mon Sep 17 00:00:00 2001 From: oddcoder Date: Sun, 26 Apr 2020 12:33:51 +0200 Subject: [PATCH 03/13] Test towlower and towupper --- tests/Makefile | 4 +++- tests/expected/wctype/towlower.stderr | 0 tests/expected/wctype/towlower.stdout | 2 ++ tests/expected/wctype/towupper.stderr | 0 tests/expected/wctype/towupper.stdout | 2 ++ tests/wctype/towlower.c | 12 ++++++++++++ tests/wctype/towupper.c | 12 ++++++++++++ 7 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/expected/wctype/towlower.stderr create mode 100644 tests/expected/wctype/towlower.stdout create mode 100644 tests/expected/wctype/towupper.stderr create mode 100644 tests/expected/wctype/towupper.stdout create mode 100644 tests/wctype/towlower.c create mode 100644 tests/wctype/towupper.c diff --git a/tests/Makefile b/tests/Makefile index 716600fa7a..6b056b4dc1 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -103,7 +103,9 @@ EXPECT_NAMES=\ wchar/wcsstr \ wchar/wcstod \ wchar/wcstok \ - wchar/wcstol + wchar/wcstol \ + wctype/towlower \ + wctype/towupper # TODO: Fix these # mkfifo diff --git a/tests/expected/wctype/towlower.stderr b/tests/expected/wctype/towlower.stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/expected/wctype/towlower.stdout b/tests/expected/wctype/towlower.stdout new file mode 100644 index 0000000000..fdbf17836f --- /dev/null +++ b/tests/expected/wctype/towlower.stdout @@ -0,0 +1,2 @@ +HaLf WiDe ChAr StRiNg! +half wide char string! diff --git a/tests/expected/wctype/towupper.stderr b/tests/expected/wctype/towupper.stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/expected/wctype/towupper.stdout b/tests/expected/wctype/towupper.stdout new file mode 100644 index 0000000000..a09771e7bc --- /dev/null +++ b/tests/expected/wctype/towupper.stdout @@ -0,0 +1,2 @@ +HaLf WiDe ChAr StRiNg! +HALF WIDE CHAR STRING! diff --git a/tests/wctype/towlower.c b/tests/wctype/towlower.c new file mode 100644 index 0000000000..a99d4252bd --- /dev/null +++ b/tests/wctype/towlower.c @@ -0,0 +1,12 @@ +#include +#include +#include + +int main() { + wchar_t *str = L"HaLf WiDe ChAr StRiNg!\n"; + fputws(str, stdout); + for (int i = 0; i < wcslen(str); i++) { + putwchar(towlower(str[i])); + } + return 0; +} \ No newline at end of file diff --git a/tests/wctype/towupper.c b/tests/wctype/towupper.c new file mode 100644 index 0000000000..61fb09edf4 --- /dev/null +++ b/tests/wctype/towupper.c @@ -0,0 +1,12 @@ +#include +#include +#include + +int main() { + wchar_t *str = L"HaLf WiDe ChAr StRiNg!\n"; + fputws(str, stdout); + for (int i = 0; i < wcslen(str); i++) { + putwchar(towupper(str[i])); + } + return 0; +} \ No newline at end of file From eac69c920d53b55880c7de3ad0bd6f1644585b1e Mon Sep 17 00:00:00 2001 From: oddcoder Date: Sun, 26 Apr 2020 12:39:18 +0200 Subject: [PATCH 04/13] Implement wcscasecmp and wcsncasecmp This patch implements wcscasecmp and wcsncasecmp. These two function are required for binutils to link against relibc. --- src/header/wchar/mod.rs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/header/wchar/mod.rs b/src/header/wchar/mod.rs index ad371d8c68..4c4a281bbd 100644 --- a/src/header/wchar/mod.rs +++ b/src/header/wchar/mod.rs @@ -726,3 +726,35 @@ pub extern "C" fn wprintf(format: *const wchar_t, ap: va_list) -> c_int { pub extern "C" fn wscanf(format: *const wchar_t, ap: va_list) -> c_int { unimplemented!(); } + +#[no_mangle] +pub extern "C" fn wcscasecmp(mut s1: *const wchar_t, mut s2: *const wchar_t) -> c_int { + unsafe { + while *s1 != 0 && *s2 != 0 { + if towlower(*s1 as wint_t) != towlower(*s2 as wint_t) { + break; + } + s1 = s1.add(1); + s2 = s2.add(1); + } + let result = towlower(*s1 as wint_t).wrapping_sub(towlower(*s2 as wint_t)); + return result as c_int; + } +} + +#[no_mangle] +pub extern "C" fn wcsncasecmp(mut s1: *const wchar_t, mut s2: *const wchar_t, n: size_t) -> c_int { + if n == 0 { + return 0; + } + unsafe { + for _ in 0..n { + if *s1 == 0 || *s2 == 0 || towlower(*s1 as wint_t) != towlower(*s2 as wint_t) { + return towlower(*s1 as wint_t).wrapping_sub(towlower(*s2 as wint_t)) as c_int; + } + s1 = s1.add(1); + s2 = s2.add(1); + } + return 0; + } +} From e9615065acd86735758c579a892c070d8186bc90 Mon Sep 17 00:00:00 2001 From: oddcoder Date: Sun, 26 Apr 2020 19:05:50 +0200 Subject: [PATCH 05/13] Add tests for both wcsncasecmp and wcscasecmp --- tests/Makefile | 2 ++ tests/expected/wchar/wcscasecmp.stderr | 0 tests/expected/wchar/wcscasecmp.stdout | 4 ++++ tests/expected/wchar/wcsncasecmp.stderr | 0 tests/expected/wchar/wcsncasecmp.stdout | 5 +++++ tests/wchar/wcscasecmp.c | 11 +++++++++++ tests/wchar/wcsncasecmp.c | 12 ++++++++++++ 7 files changed, 34 insertions(+) create mode 100644 tests/expected/wchar/wcscasecmp.stderr create mode 100644 tests/expected/wchar/wcscasecmp.stdout create mode 100644 tests/expected/wchar/wcsncasecmp.stderr create mode 100644 tests/expected/wchar/wcsncasecmp.stdout create mode 100644 tests/wchar/wcscasecmp.c create mode 100644 tests/wchar/wcsncasecmp.c diff --git a/tests/Makefile b/tests/Makefile index 6b056b4dc1..eec484b078 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -104,6 +104,8 @@ EXPECT_NAMES=\ wchar/wcstod \ wchar/wcstok \ wchar/wcstol \ + wchar/wcscasecmp \ + wchar/wcsncasecmp \ wctype/towlower \ wctype/towupper # TODO: Fix these diff --git a/tests/expected/wchar/wcscasecmp.stderr b/tests/expected/wchar/wcscasecmp.stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/expected/wchar/wcscasecmp.stdout b/tests/expected/wchar/wcscasecmp.stdout new file mode 100644 index 0000000000..fdd11f6552 --- /dev/null +++ b/tests/expected/wchar/wcscasecmp.stdout @@ -0,0 +1,4 @@ +wcscasecmp(s1, s1) = 0 +wcscasecmp(s1, s2) = -1 +wcscasecmp(s2, s1) = 1 +wcscasecmp(s2, s2) = 0 diff --git a/tests/expected/wchar/wcsncasecmp.stderr b/tests/expected/wchar/wcsncasecmp.stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/expected/wchar/wcsncasecmp.stdout b/tests/expected/wchar/wcsncasecmp.stdout new file mode 100644 index 0000000000..6a4bd43fc4 --- /dev/null +++ b/tests/expected/wchar/wcsncasecmp.stdout @@ -0,0 +1,5 @@ +wcsncasecmp(s1, s1, 17) = 0 +wcsncasecmp(s1, s2, 17) = -1 +wcsncasecmp(s2, s1, 17) = 1 +wcsncasecmp(s2, s1, 15) = 0 +wcsncasecmp(s1, s2, 0) = 0 diff --git a/tests/wchar/wcscasecmp.c b/tests/wchar/wcscasecmp.c new file mode 100644 index 0000000000..7241be198a --- /dev/null +++ b/tests/wchar/wcscasecmp.c @@ -0,0 +1,11 @@ +#include +#include + +int main() { + wchar_t *s1 = L"ThIs Is StRiNg 1."; + wchar_t *s2 = L"tHiS iS sTrInG 2."; + printf("wcscasecmp(s1, s1) = %d\n", wcscasecmp(s1, s1)); + printf("wcscasecmp(s1, s2) = %d\n", wcscasecmp(s1, s2)); + printf("wcscasecmp(s2, s1) = %d\n", wcscasecmp(s2, s1)); + printf("wcscasecmp(s2, s2) = %d\n", wcscasecmp(s2, s2)); +} diff --git a/tests/wchar/wcsncasecmp.c b/tests/wchar/wcsncasecmp.c new file mode 100644 index 0000000000..d0e815fe6e --- /dev/null +++ b/tests/wchar/wcsncasecmp.c @@ -0,0 +1,12 @@ +#include +#include + +int main() { + wchar_t *s1 = L"This is string 1."; + wchar_t *s2 = L"This is string 2."; + printf("wcsncasecmp(s1, s1, 17) = %d\n", wcsncasecmp(s1, s1, 17)); + printf("wcsncasecmp(s1, s2, 17) = %d\n", wcsncasecmp(s1, s2, 17)); + printf("wcsncasecmp(s2, s1, 17) = %d\n", wcsncasecmp(s2, s1, 17)); + printf("wcsncasecmp(s2, s1, 15) = %d\n", wcsncasecmp(s2, s1, 15)); + printf("wcsncasecmp(s1, s2, 0) = %d\n", wcsncasecmp(s1, s2, 0)); +} From 1182d1200603c9f33ec9968a1a00df5ebd3aa7d8 Mon Sep 17 00:00:00 2001 From: oddcoder Date: Sun, 3 May 2020 09:48:55 +0200 Subject: [PATCH 06/13] Fill gaps in binary memory image Some ELFs can have gaps between the segments, this results in problems when mprotecting or when converting (addr + size) into rust slice. Motivated by this This patch will fill these gaps with mmaped addresses. In theory no real memory should be allocated because mmap is lazy allocator. --- src/ld_so/linker.rs | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs index fbd7dd0abd..118122f6bc 100644 --- a/src/ld_so/linker.rs +++ b/src/ld_so/linker.rs @@ -383,7 +383,6 @@ impl Linker { } // Allocate memory let mmap = unsafe { - let size = bounds.1 /* - bounds.0 */; let same_elf = if let Some(prog) = dso.as_ref() { if prog.name == *elf_name { true @@ -395,6 +394,36 @@ impl Linker { }; if same_elf { let addr = dso.as_ref().unwrap().base_addr; + let mut size = bounds.1; + // Fill the gaps i the binary + let mut ranges = Vec::new(); + for ph in elf.program_headers.iter() { + if ph.p_type == program_header::PT_LOAD { + let voff = ph.p_vaddr as usize % PAGE_SIZE; + let vaddr = ph.p_vaddr as usize - voff; + let vsize = ((ph.p_memsz as usize + voff + PAGE_SIZE - 1) / PAGE_SIZE) + * PAGE_SIZE; + ranges.push((vaddr, vsize)); + } + } + ranges.sort(); + let mut start = addr; + for (vaddr, vsize) in ranges.iter() { + if start < addr + vaddr { + let gap_size = addr + vaddr - start; + size += gap_size; + sys_mman::mmap( + start as *mut c_void, + addr + vaddr - start, + //TODO: Make it possible to not specify PROT_EXEC on Redox + sys_mman::PROT_READ | sys_mman::PROT_WRITE, + sys_mman::MAP_ANONYMOUS | sys_mman::MAP_PRIVATE, + -1, + 0, + ); + } + start = addr + vaddr + vsize + } sys_mman::mprotect( addr as *mut c_void, size, @@ -403,6 +432,7 @@ impl Linker { _r_debug.insert(addr as usize, &elf_name, addr + l_ld as usize); slice::from_raw_parts_mut(addr as *mut u8, size) } else { + let size = bounds.1; let ptr = sys_mman::mmap( ptr::null_mut(), size, From 67be05d3a350a9a4d4db0c07366cad9b93d66610 Mon Sep 17 00:00:00 2001 From: oddcoder Date: Sun, 3 May 2020 12:33:55 +0200 Subject: [PATCH 07/13] Use segments instead of sections for calculating which offset to write, I noticed that the implementation is noth precise although it worked. and instead of using the sections to identify memory addresses of DT_DEBUG. I used segements --- src/ld_so/linker.rs | 49 ++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs index 118122f6bc..8fc7bc876b 100644 --- a/src/ld_so/linker.rs +++ b/src/ld_so/linker.rs @@ -689,29 +689,36 @@ impl Linker { } } - // overwrite DT_DEBUG if exist in .dynamic section - for section in &elf.section_headers { - // we won't bother with half corrupted elfs. - let name = elf.shdr_strtab.get(section.sh_name).unwrap().unwrap(); - if name != ".dynamic" { - continue; + // overwrite DT_DEBUG if exist in DYNAMIC segment + // first we identify the location of DYNAMIC segment + let mut dyn_start = None; + let mut debug_start = None; + for ph in elf.program_headers.iter() { + if ph.p_type == program_header::PT_DYNAMIC { + dyn_start = Some(ph.p_vaddr as usize); } - let mmap = match self.mmaps.get_mut(*elf_name) { - Some(some) => some, - None => continue, - }; - let dyn_start = section.sh_addr as usize; - let bytes: [u8; size_of::() / 2] = - unsafe { transmute((&_r_debug) as *const RTLDDebug as usize) }; - if let Some(dynamic) = elf.dynamic.as_ref() { - let mut i = 0; - for entry in &dynamic.dyns { - if entry.d_tag == DT_DEBUG { - let start = dyn_start + i * size_of::() + size_of::() / 2; - mmap[start..start + size_of::() / 2].clone_from_slice(&bytes); - } - i += 1; + } + // next we identify the location of DT_DEBUG in .dynamic section + if let Some(dynamic) = elf.dynamic.as_ref() { + let mut i = 0; + for entry in &dynamic.dyns { + if entry.d_tag == DT_DEBUG { + debug_start = Some(i as usize); + break; } + i += 1; + } + } + if let Some(dyn_start_addr) = dyn_start { + if let Some(i) = debug_start { + let mmap = match self.mmaps.get_mut(*elf_name) { + Some(some) => some, + None => continue, + }; + let bytes: [u8; size_of::() / 2] = + unsafe { transmute((&_r_debug) as *const RTLDDebug as usize) }; + let start = dyn_start_addr + i * size_of::() + size_of::() / 2; + mmap[start..start + size_of::() / 2].clone_from_slice(&bytes); } } From 850dfd971b54d1864331478e56b202d691fa83b2 Mon Sep 17 00:00:00 2001 From: oddcoder Date: Sun, 3 May 2020 12:35:01 +0200 Subject: [PATCH 08/13] Make "./a.out" entry the first in rmap list This fixes a regression in gdb where sometimes it decides to ignore the first entry in the list. --- src/ld_so/debug.rs | 15 ++++++++++++++- src/ld_so/linker.rs | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/ld_so/debug.rs b/src/ld_so/debug.rs index 8780cc1f26..d6838e08a7 100644 --- a/src/ld_so/debug.rs +++ b/src/ld_so/debug.rs @@ -52,6 +52,16 @@ impl RTLDDebug { } return; } + pub fn insert_first(&mut self, l_addr: usize, name: &str, l_ld: usize) { + if self.r_map.is_null() { + self.r_map = LinkMap::new_with_args(l_addr, name, l_ld); + } else { + let tmp = self.r_map; + self.r_map = LinkMap::new_with_args(l_addr, name, l_ld); + unsafe { (*self.r_map).link(&mut *tmp) }; + } + return; + } } #[repr(C)] @@ -80,7 +90,10 @@ impl LinkMap { }); Box::into_raw(map) } - + fn link(&mut self, map: &mut LinkMap) { + map.l_prev = self as *mut LinkMap; + self.l_next = map as *mut LinkMap; + } fn new_with_args(l_addr: usize, name: &str, l_ld: usize) -> *mut Self { let map = LinkMap::new(); unsafe { diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs index 8fc7bc876b..1b47d5c38e 100644 --- a/src/ld_so/linker.rs +++ b/src/ld_so/linker.rs @@ -429,7 +429,7 @@ impl Linker { size, sys_mman::PROT_READ | sys_mman::PROT_WRITE, ); - _r_debug.insert(addr as usize, &elf_name, addr + l_ld as usize); + _r_debug.insert_first(addr as usize, &elf_name, addr + l_ld as usize); slice::from_raw_parts_mut(addr as *mut u8, size) } else { let size = bounds.1; From d62f9b681902bc65224bdc89162bd819609782e3 Mon Sep 17 00:00:00 2001 From: oddcoder Date: Fri, 8 May 2020 00:59:19 +0200 Subject: [PATCH 09/13] Fix regression in ld.so elf size calculation In patch 1182d1200603c9f33ec9968a1a00df5ebd3aa7d8, I mistakingly added the size of the gap to the total size of the binary, which was not accurate. As the size of the binary was calculate by subtracting the upperbound from the lower bound, thus all gaps in the middle are taking into account. --- src/ld_so/linker.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs index 1b47d5c38e..47331f5af6 100644 --- a/src/ld_so/linker.rs +++ b/src/ld_so/linker.rs @@ -394,7 +394,7 @@ impl Linker { }; if same_elf { let addr = dso.as_ref().unwrap().base_addr; - let mut size = bounds.1; + let size = bounds.1; // Fill the gaps i the binary let mut ranges = Vec::new(); for ph in elf.program_headers.iter() { @@ -410,8 +410,6 @@ impl Linker { let mut start = addr; for (vaddr, vsize) in ranges.iter() { if start < addr + vaddr { - let gap_size = addr + vaddr - start; - size += gap_size; sys_mman::mmap( start as *mut c_void, addr + vaddr - start, From 4a47bc4a6f4421c374dd2f10fbd5b40787aee98a Mon Sep 17 00:00:00 2001 From: oddcoder Date: Fri, 8 May 2020 01:04:21 +0200 Subject: [PATCH 10/13] Fix regressing in printf padding with space There was bug in printf where space paddings cause segfault, the problem was that it was pulled from the stack twice while it should be only done once. --- src/header/stdio/printf.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/header/stdio/printf.rs b/src/header/stdio/printf.rs index d8b06bc70f..727de95264 100644 --- a/src/header/stdio/printf.rs +++ b/src/header/stdio/printf.rs @@ -472,7 +472,6 @@ struct PrintfArg { sign_always: bool, min_width: Number, precision: Option, - pad_space: Number, pad_zero: Number, intkind: IntKind, fmt: u8, @@ -596,7 +595,6 @@ impl Iterator for PrintfIter { sign_always, min_width, precision, - pad_space, pad_zero, intkind, fmt, @@ -667,8 +665,11 @@ unsafe fn inner_printf(w: W, format: *const c_char, mut ap: VaList) -> let sign_always = arg.sign_always; let min_width = arg.min_width.resolve(&mut varargs, &mut ap); let precision = arg.precision.map(|n| n.resolve(&mut varargs, &mut ap)); - let pad_space = arg.pad_space.resolve(&mut varargs, &mut ap); let pad_zero = arg.pad_zero.resolve(&mut varargs, &mut ap); + let pad_space = match pad_zero { + 0 => min_width, + _ => 0, + }; let intkind = arg.intkind; let fmt = arg.fmt; let fmtkind = arg.fmtkind; From d373bcb032952aebb8f17d55bc80c4925b3518a8 Mon Sep 17 00:00:00 2001 From: oddcoder Date: Fri, 8 May 2020 22:36:59 +0200 Subject: [PATCH 11/13] Avoid accessing memory without initialization --- tests/error.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/error.c b/tests/error.c index 5cbe10385d..4170e1f4be 100644 --- a/tests/error.c +++ b/tests/error.c @@ -20,7 +20,7 @@ int main(void) { int ret2 = strerror_r(err, buf2, 3); printf("errno: %d = %s, return: %d\n", err, buf2, ret2); - char buf3[256]; + char buf3[256] = {0}; int ret3 = strerror_r(err, buf3, 0); printf("errno: %d = %s, return: %d\n", err, buf3, ret3); } From a39447e6a479af7770aaf0d6cad51285868214b2 Mon Sep 17 00:00:00 2001 From: oddcoder Date: Fri, 8 May 2020 22:37:39 +0200 Subject: [PATCH 12/13] Test printf space padding regression --- tests/Makefile | 1 + tests/expected/stdio/printf_space_pad.stderr | 0 tests/expected/stdio/printf_space_pad.stdout | 1 + tests/stdio/printf_space_pad.c | 4 ++++ 4 files changed, 6 insertions(+) create mode 100644 tests/expected/stdio/printf_space_pad.stderr create mode 100644 tests/expected/stdio/printf_space_pad.stdout create mode 100644 tests/stdio/printf_space_pad.c diff --git a/tests/Makefile b/tests/Makefile index eec484b078..a6f967a872 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -41,6 +41,7 @@ EXPECT_NAMES=\ stdio/scanf \ stdio/setvbuf \ stdio/sprintf \ + stdio/printf_space_pad \ stdlib/a64l \ stdlib/alloc \ stdlib/atof \ diff --git a/tests/expected/stdio/printf_space_pad.stderr b/tests/expected/stdio/printf_space_pad.stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/expected/stdio/printf_space_pad.stdout b/tests/expected/stdio/printf_space_pad.stdout new file mode 100644 index 0000000000..8e9107f351 --- /dev/null +++ b/tests/expected/stdio/printf_space_pad.stdout @@ -0,0 +1 @@ +A B diff --git a/tests/stdio/printf_space_pad.c b/tests/stdio/printf_space_pad.c new file mode 100644 index 0000000000..9e9172826d --- /dev/null +++ b/tests/stdio/printf_space_pad.c @@ -0,0 +1,4 @@ +#include +int main() { + printf ("%s%*s\n","A", 3, "B"); +} From 43fbaf9970ebe04c81c5544133480e74fd745a69 Mon Sep 17 00:00:00 2001 From: oddcoder Date: Wed, 13 May 2020 23:27:16 +0200 Subject: [PATCH 13/13] Fix a bug in thread local reloations There was a bug (also uncovered via binutils) where R_X86_64_DTPOFF64 is set uncorrectly. This program is the minimal reproducer of the seg fault #include int main() { int oerrno = errno; } But it works after the bug fix. --- src/ld_so/linker.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs index 47331f5af6..4aea9b4100 100644 --- a/src/ld_so/linker.rs +++ b/src/ld_so/linker.rs @@ -666,7 +666,7 @@ impl Linker { set_u64(tm as u64); } reloc::R_X86_64_DTPOFF64 => { - set_u64((s + a) as u64); + set_u64(rel.r_offset as u64); } reloc::R_X86_64_GLOB_DAT | reloc::R_X86_64_JUMP_SLOT => { set_u64(s as u64);