mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2024-11-24 10:54:16 +00:00
Flesh out skyline::libc
This commit is contained in:
parent
bf62626917
commit
0f6c365733
7 changed files with 357 additions and 73 deletions
14
link.T
14
link.T
|
@ -17,7 +17,7 @@ SECTIONS
|
||||||
|
|
||||||
.text : ALIGN(0x1000) {
|
.text : ALIGN(0x1000) {
|
||||||
HIDDEN(__text_start = .);
|
HIDDEN(__text_start = .);
|
||||||
KEEP(*(.nro_header))
|
*(.nro_header)
|
||||||
KEEP(*(.text.jmp))
|
KEEP(*(.text.jmp))
|
||||||
|
|
||||||
. = 0x80;
|
. = 0x80;
|
||||||
|
@ -32,7 +32,17 @@ SECTIONS
|
||||||
|
|
||||||
. = ALIGN(0x1000);
|
. = ALIGN(0x1000);
|
||||||
.module_name : { KEEP (*(.rodata.module_name)) } :rodata
|
.module_name : { KEEP (*(.rodata.module_name)) } :rodata
|
||||||
.rodata : { *(.rodata .rodata.*) } :rodata
|
|
||||||
|
.hooks : {
|
||||||
|
__hook_array_start = .;
|
||||||
|
*(.rodata.hooks)
|
||||||
|
__hook_array_end = .;
|
||||||
|
} :rodata
|
||||||
|
|
||||||
|
.rodata : {
|
||||||
|
*(.rodata .rodata.*)
|
||||||
|
} :rodata
|
||||||
|
|
||||||
.mod0 : {
|
.mod0 : {
|
||||||
KEEP(crt0.nso.o(.data.mod0))
|
KEEP(crt0.nso.o(.data.mod0))
|
||||||
KEEP(crt0.nro.o(.data.mod0))
|
KEEP(crt0.nro.o(.data.mod0))
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use quote::{ToTokens, quote};
|
use quote::{ToTokens, quote};
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use syn::{parse_macro_input, token, Token, Ident, Path, AttrStyle, punctuated::Punctuated};
|
use syn::{parse_macro_input, token, Ident, AttrStyle};
|
||||||
use proc_macro2::{Span, TokenStream as TokenStream2};
|
use proc_macro2::{Span, TokenStream as TokenStream2};
|
||||||
use syn::parse::Parser;
|
|
||||||
|
|
||||||
|
|
||||||
fn new_attr(attr_name: &str) -> syn::Attribute {
|
fn new_attr(attr_name: &str) -> syn::Attribute {
|
||||||
|
@ -38,66 +37,50 @@ pub fn main(_: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn hook(_: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn hook(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
let mod_fn = parse_macro_input!(input as syn::ItemFn);
|
let mut mod_fn = parse_macro_input!(input as syn::ItemFn);
|
||||||
let mut output = TokenStream2::new();
|
let mut output = TokenStream2::new();
|
||||||
|
|
||||||
|
// #[no_mangle]
|
||||||
|
mod_fn.attrs.push(
|
||||||
|
new_attr("no_mangle")
|
||||||
|
);
|
||||||
|
|
||||||
|
// extern "C"
|
||||||
|
mod_fn.sig.abi = Some(syn::Abi {
|
||||||
|
extern_token: syn::token::Extern { span: Span::call_site() },
|
||||||
|
name: Some(syn::LitStr::new("C", Span::call_site()))
|
||||||
|
});
|
||||||
|
|
||||||
mod_fn.to_tokens(&mut output);
|
mod_fn.to_tokens(&mut output);
|
||||||
|
|
||||||
let ident = quote::format_ident!(
|
let mod_fn = mod_fn.sig.ident;
|
||||||
|
|
||||||
|
let info = quote::format_ident!(
|
||||||
"{}_skyline_internal_hook_info",
|
"{}_skyline_internal_hook_info",
|
||||||
mod_fn.sig.ident
|
mod_fn
|
||||||
|
);
|
||||||
|
|
||||||
|
let hook = quote::format_ident!(
|
||||||
|
"{}_skyline_internal_hook",
|
||||||
|
mod_fn
|
||||||
);
|
);
|
||||||
|
|
||||||
quote!(
|
quote!(
|
||||||
#[allow(non_upper_case_globals)]
|
/*#[allow(non_upper_case_globals)]
|
||||||
const #ident: ::skyline::hooks::HookInfo = ::skyline::hooks::HookInfo {
|
static #info: ::skyline::hooks::HookInfo = ::skyline::hooks::HookInfo {
|
||||||
name: None,
|
name: None,
|
||||||
|
fn_name: stringify!(#mod_fn),
|
||||||
offset: None,
|
offset: None,
|
||||||
symbol: None,
|
symbol: None,
|
||||||
inline: false
|
inline: false
|
||||||
};
|
};
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
#[link_section = ".rodata.hooks"]
|
||||||
|
static #hook: ::skyline::hooks::Hook = ::skyline::hooks::Hook{
|
||||||
|
ptr: #mod_fn as *const (),
|
||||||
|
info: &#info
|
||||||
|
};*/
|
||||||
).to_tokens(&mut output);
|
).to_tokens(&mut output);
|
||||||
|
|
||||||
output.into()
|
output.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_hook_fns(input: TokenStream) -> syn::Result<Vec<Path>> {
|
|
||||||
Ok(
|
|
||||||
Punctuated::<Path, Token![,]>::parse_terminated
|
|
||||||
.parse(input)?
|
|
||||||
.into_iter()
|
|
||||||
.collect()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn concat_path(path: &Path) -> Path {
|
|
||||||
let mut path = path.clone();
|
|
||||||
|
|
||||||
let last = path.segments.iter_mut().last().unwrap();
|
|
||||||
|
|
||||||
last.ident = quote::format_ident!("{}_skyline_internal_hook_info", last.ident);
|
|
||||||
|
|
||||||
path
|
|
||||||
}
|
|
||||||
|
|
||||||
#[proc_macro]
|
|
||||||
pub fn hooks(tokens: TokenStream) -> TokenStream {
|
|
||||||
parse_hook_fns(tokens)
|
|
||||||
.map(|hook_fns|{
|
|
||||||
let hook_fn_infos = hook_fns.iter().map(concat_path);
|
|
||||||
quote!{
|
|
||||||
::skyline::hooks::Hooks(::skyline::alloc::vec![
|
|
||||||
#(
|
|
||||||
::skyline::new_hook!(
|
|
||||||
#hook_fns,
|
|
||||||
#hook_fn_infos
|
|
||||||
)
|
|
||||||
),*
|
|
||||||
])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.unwrap_or_else(|e|{
|
|
||||||
e.to_compile_error()
|
|
||||||
})
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
|
|
|
@ -14,7 +14,10 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
|
|
||||||
global_asm!(include_str!("mod0.s"));
|
global_asm!(include_str!("mod0.s"));
|
||||||
|
|
||||||
#[no_mangle] pub extern "C" fn __custom_init() {}
|
#[no_mangle] pub unsafe extern "C" fn __custom_init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[no_mangle] pub extern "C" fn __custom_fini() {}
|
#[no_mangle] pub extern "C" fn __custom_fini() {}
|
||||||
|
|
||||||
#[repr(packed)]
|
#[repr(packed)]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::alloc::string::String;
|
use crate::alloc::string::String;
|
||||||
use crate::alloc::vec::Vec;
|
|
||||||
|
|
||||||
pub struct HookInfo {
|
pub struct HookInfo {
|
||||||
|
pub fn_name: &'static str,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub offset: Option<u64>,
|
pub offset: Option<u64>,
|
||||||
pub symbol: Option<String>,
|
pub symbol: Option<String>,
|
||||||
|
@ -10,7 +10,11 @@ pub struct HookInfo {
|
||||||
|
|
||||||
pub struct Hook {
|
pub struct Hook {
|
||||||
pub ptr: *const (),
|
pub ptr: *const (),
|
||||||
pub info: &'static HookInfo
|
pub info: &'static HookInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Sync for Hook {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hook {
|
impl Hook {
|
||||||
|
@ -19,21 +23,27 @@ impl Hook {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Hooks(pub Vec<Hook>);
|
#[allow(improper_ctypes)]
|
||||||
|
extern "C" {
|
||||||
impl Hooks {
|
static __hook_array_start: Hook;
|
||||||
pub fn install_hooks(&self) {
|
static __hook_array_end: Hook;
|
||||||
for hook in &self.0 {
|
|
||||||
hook.install();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export] macro_rules! new_hook {
|
pub fn iter_hooks() -> impl Iterator<Item = &'static Hook> {
|
||||||
($path:path, $info:path) => {
|
let hook_start = unsafe {&__hook_array_start as *const Hook};
|
||||||
$crate::hooks::Hook {
|
let hook_end = unsafe {&__hook_array_end as *const Hook};
|
||||||
ptr: $path as *const (),
|
|
||||||
info: &$info
|
let hook_count = ((hook_start as usize) - (hook_end as usize)) / core::mem::size_of::<Hook>();
|
||||||
}
|
|
||||||
};
|
crate::println!("hook_count: {}", hook_count);
|
||||||
|
crate::println!("hook_start: {:?}", hook_start);
|
||||||
|
crate::println!("hook_end: {:?}", hook_start);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
core::slice::from_raw_parts(
|
||||||
|
hook_start,
|
||||||
|
hook_count
|
||||||
|
)
|
||||||
|
}.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,8 @@ pub mod hooks;
|
||||||
pub mod build;
|
pub mod build;
|
||||||
pub mod extern_alloc;
|
pub mod extern_alloc;
|
||||||
pub use extern_alloc::Allocator;
|
pub use extern_alloc::Allocator;
|
||||||
pub use skyline_macro::{main, hook, hooks};
|
pub use skyline_macro::{main, hook};
|
||||||
|
pub use hooks::iter_hooks;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn skyline_tcp_send_raw(bytes: *const u8, usize: u64);
|
fn skyline_tcp_send_raw(bytes: *const u8, usize: u64);
|
||||||
|
|
|
@ -1,8 +1,64 @@
|
||||||
//! Public exports of libc functions
|
//! Public exports of libc functions
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
pub use core::ffi::c_void;
|
pub use core::ffi::c_void;
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
pub type c_char = u8;
|
||||||
type size_t = usize;
|
pub type time_t = i32;
|
||||||
|
pub type wchar_t = u16;
|
||||||
|
pub type c_long = i64;
|
||||||
|
|
||||||
|
pub type c_schar = i8;
|
||||||
|
pub type c_uchar = u8;
|
||||||
|
pub type c_short = i16;
|
||||||
|
pub type c_ushort = u16;
|
||||||
|
pub type c_int = i32;
|
||||||
|
pub type c_uint = u32;
|
||||||
|
pub type c_float = f32;
|
||||||
|
pub type c_double = f64;
|
||||||
|
pub type c_longlong = i64;
|
||||||
|
pub type c_ulonglong = u64;
|
||||||
|
pub type intmax_t = i64;
|
||||||
|
pub type uintmax_t = u64;
|
||||||
|
|
||||||
|
pub type size_t = usize;
|
||||||
|
pub type ptrdiff_t = isize;
|
||||||
|
pub type intptr_t = isize;
|
||||||
|
pub type uintptr_t = usize;
|
||||||
|
pub type ssize_t = isize;
|
||||||
|
|
||||||
|
pub type pid_t = i32;
|
||||||
|
pub type uid_t = u32;
|
||||||
|
pub type gid_t = u32;
|
||||||
|
pub type in_addr_t = u32;
|
||||||
|
pub type in_port_t = u16;
|
||||||
|
|
||||||
|
pub type mode_t = c_uint;
|
||||||
|
pub type off_t = i64;
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct sem_t { // Unverified
|
||||||
|
__size: [c_char; 16],
|
||||||
|
}
|
||||||
|
pub type pthread_key_t = c_uint;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct tm {
|
||||||
|
pub tm_sec: c_int,
|
||||||
|
pub tm_min: c_int,
|
||||||
|
pub tm_hour: c_int,
|
||||||
|
pub tm_mday: c_int,
|
||||||
|
pub tm_mon: c_int,
|
||||||
|
pub tm_year: c_int,
|
||||||
|
pub tm_wday: c_int,
|
||||||
|
pub tm_yday: c_int,
|
||||||
|
pub tm_isdst: c_int,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum FILE {}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum DIR {}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn malloc(size: size_t) -> *const c_void;
|
pub fn malloc(size: size_t) -> *const c_void;
|
||||||
|
@ -11,3 +67,222 @@ extern "C" {
|
||||||
pub fn realloc(ptr: *const c_void, size: size_t) -> *const c_void;
|
pub fn realloc(ptr: *const c_void, size: size_t) -> *const c_void;
|
||||||
// fn aligned_alloc(align: usize, size: usize) -> *const c_void;
|
// fn aligned_alloc(align: usize, size: usize) -> *const c_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
pub fn isalnum(c: c_int) -> c_int;
|
||||||
|
pub fn isalpha(c: c_int) -> c_int;
|
||||||
|
pub fn iscntrl(c: c_int) -> c_int;
|
||||||
|
pub fn isdigit(c: c_int) -> c_int;
|
||||||
|
pub fn isgraph(c: c_int) -> c_int;
|
||||||
|
pub fn islower(c: c_int) -> c_int;
|
||||||
|
pub fn isprint(c: c_int) -> c_int;
|
||||||
|
pub fn ispunct(c: c_int) -> c_int;
|
||||||
|
pub fn isspace(c: c_int) -> c_int;
|
||||||
|
pub fn isupper(c: c_int) -> c_int;
|
||||||
|
pub fn isxdigit(c: c_int) -> c_int;
|
||||||
|
pub fn isblank(c: c_int) -> c_int;
|
||||||
|
pub fn tolower(c: c_int) -> c_int;
|
||||||
|
pub fn toupper(c: c_int) -> c_int;
|
||||||
|
|
||||||
|
pub fn qsort(
|
||||||
|
base: *mut c_void,
|
||||||
|
num: size_t,
|
||||||
|
size: size_t,
|
||||||
|
compar: Option<
|
||||||
|
unsafe extern "C" fn(*const c_void, *const c_void) -> c_int,
|
||||||
|
>,
|
||||||
|
);
|
||||||
|
pub fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE;
|
||||||
|
pub fn fflush(file: *mut FILE) -> c_int;
|
||||||
|
pub fn fclose(file: *mut FILE) -> c_int;
|
||||||
|
pub fn remove(filename: *const c_char) -> c_int;
|
||||||
|
pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int;
|
||||||
|
pub fn setvbuf(
|
||||||
|
stream: *mut FILE,
|
||||||
|
buffer: *mut c_char,
|
||||||
|
mode: c_int,
|
||||||
|
size: size_t,
|
||||||
|
) -> c_int;
|
||||||
|
pub fn setbuf(stream: *mut FILE, buf: *mut c_char);
|
||||||
|
pub fn getchar() -> c_int;
|
||||||
|
pub fn putchar(c: c_int) -> c_int;
|
||||||
|
pub fn fgetc(stream: *mut FILE) -> c_int;
|
||||||
|
pub fn fputc(c: c_int, stream: *mut FILE) -> c_int;
|
||||||
|
pub fn puts(s: *const c_char) -> c_int;
|
||||||
|
pub fn ungetc(c: c_int, stream: *mut FILE) -> c_int;
|
||||||
|
pub fn fwrite(
|
||||||
|
ptr: *const c_void,
|
||||||
|
size: size_t,
|
||||||
|
nobj: size_t,
|
||||||
|
stream: *mut FILE,
|
||||||
|
) -> size_t;
|
||||||
|
pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int;
|
||||||
|
pub fn ftell(stream: *mut FILE) -> c_long;
|
||||||
|
pub fn rewind(stream: *mut FILE);
|
||||||
|
|
||||||
|
pub fn perror(s: *const c_char);
|
||||||
|
pub fn atoi(s: *const c_char) -> c_int;
|
||||||
|
|
||||||
|
pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double;
|
||||||
|
pub fn strtol(
|
||||||
|
s: *const c_char,
|
||||||
|
endp: *mut *mut c_char,
|
||||||
|
base: c_int,
|
||||||
|
) -> c_long;
|
||||||
|
|
||||||
|
pub fn abort() -> !;
|
||||||
|
pub fn exit(status: c_int) -> !;
|
||||||
|
|
||||||
|
pub fn atexit(cb: extern "C" fn()) -> c_int;
|
||||||
|
|
||||||
|
pub fn getenv(s: *const c_char) -> *mut c_char;
|
||||||
|
|
||||||
|
pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char;
|
||||||
|
pub fn strncpy(
|
||||||
|
dst: *mut c_char,
|
||||||
|
src: *const c_char,
|
||||||
|
n: size_t,
|
||||||
|
) -> *mut c_char;
|
||||||
|
pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char;
|
||||||
|
pub fn strncat(
|
||||||
|
s: *mut c_char,
|
||||||
|
ct: *const c_char,
|
||||||
|
n: size_t,
|
||||||
|
) -> *mut c_char;
|
||||||
|
pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int;
|
||||||
|
pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int;
|
||||||
|
pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int;
|
||||||
|
pub fn strchr(cs: *const c_char, c: c_int) -> *mut c_char;
|
||||||
|
pub fn strrchr(cs: *const c_char, c: c_int) -> *mut c_char;
|
||||||
|
pub fn strspn(cs: *const c_char, ct: *const c_char) -> size_t;
|
||||||
|
pub fn strcspn(cs: *const c_char, ct: *const c_char) -> size_t;
|
||||||
|
pub fn strdup(cs: *const c_char) -> *mut c_char;
|
||||||
|
pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char;
|
||||||
|
pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char;
|
||||||
|
pub fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_int;
|
||||||
|
pub fn strncasecmp(
|
||||||
|
s1: *const c_char,
|
||||||
|
s2: *const c_char,
|
||||||
|
n: size_t,
|
||||||
|
) -> c_int;
|
||||||
|
pub fn strlen(cs: *const c_char) -> size_t;
|
||||||
|
pub fn strnlen(cs: *const c_char, maxlen: size_t) -> size_t;
|
||||||
|
|
||||||
|
pub fn strerror(n: c_int) -> *mut c_char;
|
||||||
|
pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char;
|
||||||
|
pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t;
|
||||||
|
|
||||||
|
pub fn wcslen(buf: *const wchar_t) -> size_t;
|
||||||
|
pub fn wcstombs(
|
||||||
|
dest: *mut c_char,
|
||||||
|
src: *const wchar_t,
|
||||||
|
n: size_t,
|
||||||
|
) -> size_t;
|
||||||
|
|
||||||
|
pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void;
|
||||||
|
pub fn wmemchr(cx: *const wchar_t, c: wchar_t, n: size_t) -> *mut wchar_t;
|
||||||
|
pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int;
|
||||||
|
pub fn memcpy(
|
||||||
|
dest: *mut c_void,
|
||||||
|
src: *const c_void,
|
||||||
|
n: size_t,
|
||||||
|
) -> *mut c_void;
|
||||||
|
|
||||||
|
pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void;
|
||||||
|
|
||||||
|
pub fn fprintf(
|
||||||
|
stream: *mut FILE,
|
||||||
|
format: *const c_char,
|
||||||
|
...
|
||||||
|
) -> c_int;
|
||||||
|
pub fn printf(format: *const c_char, ...) -> c_int;
|
||||||
|
pub fn snprintf(
|
||||||
|
s: *mut c_char,
|
||||||
|
n: size_t,
|
||||||
|
format: *const c_char,
|
||||||
|
...
|
||||||
|
) -> c_int;
|
||||||
|
pub fn sprintf(s: *mut c_char, format: *const c_char, ...) -> c_int;
|
||||||
|
pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int;
|
||||||
|
|
||||||
|
pub fn access(path: *const c_char, amode: c_int) -> c_int;
|
||||||
|
|
||||||
|
pub fn chdir(dir: *const c_char) -> c_int;
|
||||||
|
|
||||||
|
pub fn close(fd: c_int) -> c_int;
|
||||||
|
|
||||||
|
pub fn getpid() -> pid_t;
|
||||||
|
|
||||||
|
pub fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t;
|
||||||
|
|
||||||
|
pub fn posix_memalign(
|
||||||
|
memptr: *mut *mut c_void,
|
||||||
|
align: size_t,
|
||||||
|
size: size_t,
|
||||||
|
) -> c_int;
|
||||||
|
|
||||||
|
pub fn rmdir(path: *const c_char) -> c_int;
|
||||||
|
pub fn sleep(secs: c_uint) -> c_uint;
|
||||||
|
pub fn read(fd: c_int, buf: *mut c_void, count: size_t)
|
||||||
|
-> ssize_t;
|
||||||
|
|
||||||
|
pub fn open(path: *const c_char, oflag: c_int, ...) -> c_int;
|
||||||
|
|
||||||
|
pub fn unlink(c: *const c_char) -> c_int;
|
||||||
|
|
||||||
|
pub fn write(
|
||||||
|
fd: c_int,
|
||||||
|
buf: *const c_void,
|
||||||
|
count: size_t,
|
||||||
|
) -> ssize_t;
|
||||||
|
|
||||||
|
pub fn pwrite(
|
||||||
|
fd: c_int,
|
||||||
|
buf: *const c_void,
|
||||||
|
count: size_t,
|
||||||
|
offset: off_t,
|
||||||
|
) -> ssize_t;
|
||||||
|
|
||||||
|
pub fn setenv(
|
||||||
|
name: *const c_char,
|
||||||
|
val: *const c_char,
|
||||||
|
overwrite: c_int,
|
||||||
|
) -> c_int;
|
||||||
|
|
||||||
|
pub fn unsetenv(name: *const c_char) -> c_int;
|
||||||
|
|
||||||
|
pub fn ftruncate(fd: c_int, length: off_t) -> c_int;
|
||||||
|
|
||||||
|
pub fn sched_yield() -> c_int;
|
||||||
|
|
||||||
|
pub fn pthread_setspecific(
|
||||||
|
key: pthread_key_t,
|
||||||
|
value: *const c_void,
|
||||||
|
) -> c_int;
|
||||||
|
|
||||||
|
pub fn mktime(tm: *mut tm) -> time_t;
|
||||||
|
pub fn time(time: *mut time_t) -> time_t;
|
||||||
|
pub fn gmtime(time_p: *const time_t) -> *mut tm;
|
||||||
|
pub fn localtime(time_p: *const time_t) -> *mut tm;
|
||||||
|
pub fn difftime(time1: time_t, time0: time_t) -> c_double;
|
||||||
|
|
||||||
|
pub fn putenv(string: *mut c_char) -> c_int;
|
||||||
|
|
||||||
|
pub fn setlocale(
|
||||||
|
category: c_int,
|
||||||
|
locale: *const c_char,
|
||||||
|
) -> *mut c_char;
|
||||||
|
|
||||||
|
pub fn sem_wait(sem: *mut sem_t) -> c_int;
|
||||||
|
pub fn sem_trywait(sem: *mut sem_t) -> c_int;
|
||||||
|
pub fn sem_post(sem: *mut sem_t) -> c_int;
|
||||||
|
|
||||||
|
pub fn strcasestr(cs: *const c_char, ct: *const c_char) -> *mut c_char;
|
||||||
|
pub fn getline(
|
||||||
|
lineptr: *mut *mut c_char,
|
||||||
|
n: *mut size_t,
|
||||||
|
stream: *mut FILE,
|
||||||
|
) -> ssize_t;
|
||||||
|
|
||||||
|
pub fn fdopendir(fd: c_int) -> *mut DIR;
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![feature(proc_macro_hygiene)]
|
#![feature(proc_macro_hygiene)]
|
||||||
|
|
||||||
use skyline::{hook, hooks};
|
use skyline::hook;
|
||||||
|
|
||||||
#[hook(sym = "nn::fs::MountSaveData")]
|
#[hook(sym = "nn::fs::MountSaveData")]
|
||||||
fn test1(path: *const u8, user_id: u64) {
|
fn test1(path: *const u8, user_id: u64) {
|
||||||
|
@ -21,5 +21,7 @@ pub fn main() {
|
||||||
println!("{}", i);
|
println!("{}", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
hooks![test1, test2].install_hooks();
|
for hook in skyline::iter_hooks() {
|
||||||
|
println!("hook: {}", hook.info.fn_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue