Enforce unsafe_op_in_unsafe_fn
This commit is contained in:
parent
dd94e27b1f
commit
28f545a5c8
@ -19,7 +19,7 @@ impl Arch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Context {
|
impl fmt::Debug for Context {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let mut fmt = fmt.debug_struct("Context");
|
let mut fmt = fmt.debug_struct("Context");
|
||||||
for i in 0..=15 {
|
for i in 0..=15 {
|
||||||
fmt.field(
|
fmt.field(
|
||||||
@ -91,43 +91,45 @@ pub extern "C-unwind" fn save_context() -> Context {
|
|||||||
|
|
||||||
#[naked]
|
#[naked]
|
||||||
pub unsafe extern "C" fn restore_context(ctx: &Context) -> ! {
|
pub unsafe extern "C" fn restore_context(ctx: &Context) -> ! {
|
||||||
asm!(
|
unsafe {
|
||||||
"
|
asm!(
|
||||||
/* Restore stack */
|
"
|
||||||
mov rsp, [rdi + 0x38]
|
/* Restore stack */
|
||||||
|
mov rsp, [rdi + 0x38]
|
||||||
|
|
||||||
/* Restore callee-saved control registers */
|
/* Restore callee-saved control registers */
|
||||||
ldmxcsr [rdi + 0x88]
|
ldmxcsr [rdi + 0x88]
|
||||||
fldcw [rdi + 0x90]
|
fldcw [rdi + 0x90]
|
||||||
|
|
||||||
/* Restore return address */
|
/* Restore return address */
|
||||||
mov rax, [rdi + 0x80]
|
mov rax, [rdi + 0x80]
|
||||||
push rax
|
push rax
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Restore general-purpose registers. Non-callee-saved registers are
|
* Restore general-purpose registers. Non-callee-saved registers are
|
||||||
* also restored because sometimes it's used to pass unwind arguments.
|
* also restored because sometimes it's used to pass unwind arguments.
|
||||||
*/
|
*/
|
||||||
mov rax, [rdi + 0x00]
|
mov rax, [rdi + 0x00]
|
||||||
mov rdx, [rdi + 0x08]
|
mov rdx, [rdi + 0x08]
|
||||||
mov rcx, [rdi + 0x10]
|
mov rcx, [rdi + 0x10]
|
||||||
mov rbx, [rdi + 0x18]
|
mov rbx, [rdi + 0x18]
|
||||||
mov rsi, [rdi + 0x20]
|
mov rsi, [rdi + 0x20]
|
||||||
mov rbp, [rdi + 0x30]
|
mov rbp, [rdi + 0x30]
|
||||||
mov r8 , [rdi + 0x40]
|
mov r8 , [rdi + 0x40]
|
||||||
mov r9 , [rdi + 0x48]
|
mov r9 , [rdi + 0x48]
|
||||||
mov r10, [rdi + 0x50]
|
mov r10, [rdi + 0x50]
|
||||||
mov r11, [rdi + 0x58]
|
mov r11, [rdi + 0x58]
|
||||||
mov r12, [rdi + 0x60]
|
mov r12, [rdi + 0x60]
|
||||||
mov r13, [rdi + 0x68]
|
mov r13, [rdi + 0x68]
|
||||||
mov r14, [rdi + 0x70]
|
mov r14, [rdi + 0x70]
|
||||||
mov r15, [rdi + 0x78]
|
mov r15, [rdi + 0x78]
|
||||||
|
|
||||||
/* RDI resotred last */
|
/* RDI resotred last */
|
||||||
mov rdi, [rdi + 0x28]
|
mov rdi, [rdi + 0x28]
|
||||||
|
|
||||||
ret
|
ret
|
||||||
",
|
",
|
||||||
options(noreturn)
|
options(noreturn)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,84 +29,96 @@ unsafe extern "C" fn phdr_callback(
|
|||||||
_size: usize,
|
_size: usize,
|
||||||
data: *mut c_void,
|
data: *mut c_void,
|
||||||
) -> c_int {
|
) -> c_int {
|
||||||
let data = &mut *(data as *mut CallbackData);
|
unsafe {
|
||||||
let phdrs = slice::from_raw_parts((*info).dlpi_phdr, (*info).dlpi_phnum as usize);
|
let data = &mut *(data as *mut CallbackData);
|
||||||
|
let phdrs = slice::from_raw_parts((*info).dlpi_phdr, (*info).dlpi_phnum as usize);
|
||||||
|
|
||||||
let mut text = None;
|
let mut text = None;
|
||||||
let mut eh_frame_hdr = None;
|
let mut eh_frame_hdr = None;
|
||||||
let mut dynamic = None;
|
let mut dynamic = None;
|
||||||
|
|
||||||
for phdr in phdrs {
|
for phdr in phdrs {
|
||||||
let start = (*info).dlpi_addr + phdr.p_vaddr;
|
let start = (*info).dlpi_addr + phdr.p_vaddr;
|
||||||
match phdr.p_type {
|
match phdr.p_type {
|
||||||
PT_LOAD => {
|
PT_LOAD => {
|
||||||
let end = start + phdr.p_memsz;
|
let end = start + phdr.p_memsz;
|
||||||
let range = start..end;
|
let range = start..end;
|
||||||
if range.contains(&(data.pc as _)) {
|
if range.contains(&(data.pc as _)) {
|
||||||
text = Some(range);
|
text = Some(range);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
PT_GNU_EH_FRAME => {
|
||||||
|
eh_frame_hdr = Some(start);
|
||||||
|
}
|
||||||
|
PT_DYNAMIC => {
|
||||||
|
dynamic = Some(start);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
PT_GNU_EH_FRAME => {
|
|
||||||
eh_frame_hdr = Some(start);
|
|
||||||
}
|
|
||||||
PT_DYNAMIC => {
|
|
||||||
dynamic = Some(start);
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let text = match text {
|
let text = match text {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => return 0,
|
None => return 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
let eh_frame_hdr = match eh_frame_hdr {
|
let eh_frame_hdr = match eh_frame_hdr {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => return 0,
|
None => return 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut bases = BaseAddresses::default()
|
let mut bases = BaseAddresses::default()
|
||||||
.set_eh_frame_hdr(eh_frame_hdr as _)
|
.set_eh_frame_hdr(eh_frame_hdr as _)
|
||||||
.set_text(text.start as _);
|
.set_text(text.start as _);
|
||||||
|
|
||||||
// Find the GOT section.
|
// Find the GOT section.
|
||||||
if let Some(start) = dynamic {
|
if let Some(start) = dynamic {
|
||||||
const DT_NULL: usize = 0;
|
const DT_NULL: usize = 0;
|
||||||
const DT_PLTGOT: usize = 3;
|
const DT_PLTGOT: usize = 3;
|
||||||
|
|
||||||
let mut tags = start as *const [usize; 2];
|
let mut tags = start as *const [usize; 2];
|
||||||
let mut tag = *tags;
|
let mut tag = *tags;
|
||||||
while tag[0] != DT_NULL {
|
while tag[0] != DT_NULL {
|
||||||
if tag[0] == DT_PLTGOT {
|
if tag[0] == DT_PLTGOT {
|
||||||
bases = bases.set_got(tag[1] as _);
|
bases = bases.set_got(tag[1] as _);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
tags = tags.add(1);
|
||||||
|
tag = *tags;
|
||||||
}
|
}
|
||||||
tags = tags.add(1);
|
|
||||||
tag = *tags;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Parse .eh_frame_hdr section.
|
// Parse .eh_frame_hdr section.
|
||||||
let eh_frame_hdr = EhFrameHdr::new(
|
let eh_frame_hdr = EhFrameHdr::new(
|
||||||
get_unlimited_slice(eh_frame_hdr as usize as _),
|
get_unlimited_slice(eh_frame_hdr as usize as _),
|
||||||
NativeEndian,
|
NativeEndian,
|
||||||
)
|
)
|
||||||
.parse(&bases, mem::size_of::<usize>() as _);
|
.parse(&bases, mem::size_of::<usize>() as _);
|
||||||
let eh_frame_hdr = match eh_frame_hdr {
|
let eh_frame_hdr = match eh_frame_hdr {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(_) => return 0,
|
Err(_) => return 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
let eh_frame = deref_pointer(eh_frame_hdr.eh_frame_ptr());
|
let eh_frame = deref_pointer(eh_frame_hdr.eh_frame_ptr());
|
||||||
bases = bases.set_eh_frame(eh_frame as _);
|
bases = bases.set_eh_frame(eh_frame as _);
|
||||||
let eh_frame = EhFrame::new(get_unlimited_slice(eh_frame as usize as _), NativeEndian);
|
let eh_frame = EhFrame::new(get_unlimited_slice(eh_frame as usize as _), NativeEndian);
|
||||||
|
|
||||||
// Use binary search table for address if available.
|
// Use binary search table for address if available.
|
||||||
if let Some(table) = eh_frame_hdr.table() {
|
if let Some(table) = eh_frame_hdr.table() {
|
||||||
if let Ok(fde) =
|
if let Ok(fde) =
|
||||||
table.fde_for_address(&eh_frame, &bases, data.pc as _, EhFrame::cie_from_offset)
|
table.fde_for_address(&eh_frame, &bases, data.pc as _, EhFrame::cie_from_offset)
|
||||||
{
|
{
|
||||||
|
data.result = Some(FDESearchResult {
|
||||||
|
fde,
|
||||||
|
bases,
|
||||||
|
eh_frame,
|
||||||
|
});
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise do the linear search.
|
||||||
|
if let Ok(fde) = eh_frame.fde_for_address(&bases, data.pc as _, EhFrame::cie_from_offset) {
|
||||||
data.result = Some(FDESearchResult {
|
data.result = Some(FDESearchResult {
|
||||||
fde,
|
fde,
|
||||||
bases,
|
bases,
|
||||||
@ -114,17 +126,7 @@ unsafe extern "C" fn phdr_callback(
|
|||||||
});
|
});
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise do the linear search.
|
0
|
||||||
if let Ok(fde) = eh_frame.fde_for_address(&bases, data.pc as _, EhFrame::cie_from_offset) {
|
|
||||||
data.result = Some(FDESearchResult {
|
|
||||||
fde,
|
|
||||||
bases,
|
|
||||||
eh_frame,
|
|
||||||
});
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
0
|
|
||||||
}
|
}
|
||||||
|
@ -41,9 +41,9 @@ pub fn get_finder() -> &'static Registry {
|
|||||||
impl super::FDEFinder for Registry {
|
impl super::FDEFinder for Registry {
|
||||||
fn find_fde(&self, pc: usize) -> Option<FDESearchResult> {
|
fn find_fde(&self, pc: usize) -> Option<FDESearchResult> {
|
||||||
let guard = get_finder().inner.lock().unwrap();
|
let guard = get_finder().inner.lock().unwrap();
|
||||||
let mut cur = guard.object;
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let mut cur = guard.object;
|
||||||
|
|
||||||
while !cur.is_null() {
|
while !cur.is_null() {
|
||||||
let bases = BaseAddresses::default()
|
let bases = BaseAddresses::default()
|
||||||
.set_text((*cur).tbase as _)
|
.set_text((*cur).tbase as _)
|
||||||
@ -103,21 +103,23 @@ unsafe extern "C" fn __register_frame_info_bases(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ob.write(Object {
|
unsafe {
|
||||||
next: core::ptr::null_mut(),
|
ob.write(Object {
|
||||||
tbase: tbase as _,
|
next: core::ptr::null_mut(),
|
||||||
dbase: dbase as _,
|
tbase: tbase as _,
|
||||||
table: Table::Single(begin),
|
dbase: dbase as _,
|
||||||
});
|
table: Table::Single(begin),
|
||||||
|
});
|
||||||
|
|
||||||
let mut guard = get_finder().inner.lock().unwrap();
|
let mut guard = get_finder().inner.lock().unwrap();
|
||||||
(*ob).next = guard.object;
|
(*ob).next = guard.object;
|
||||||
guard.object = ob;
|
guard.object = ob;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn __register_frame_info(begin: *const c_void, ob: *mut Object) {
|
unsafe extern "C" fn __register_frame_info(begin: *const c_void, ob: *mut Object) {
|
||||||
__register_frame_info_bases(begin, ob, core::ptr::null_mut(), core::ptr::null_mut());
|
unsafe { __register_frame_info_bases(begin, ob, core::ptr::null_mut(), core::ptr::null_mut()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -127,7 +129,7 @@ unsafe extern "C" fn __register_frame(begin: *const c_void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let storage = Box::into_raw(Box::new(MaybeUninit::<Object>::uninit())) as *mut Object;
|
let storage = Box::into_raw(Box::new(MaybeUninit::<Object>::uninit())) as *mut Object;
|
||||||
__register_frame_info(begin, storage);
|
unsafe { __register_frame_info(begin, storage) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -137,21 +139,25 @@ unsafe extern "C" fn __register_frame_info_table_bases(
|
|||||||
tbase: *const c_void,
|
tbase: *const c_void,
|
||||||
dbase: *const c_void,
|
dbase: *const c_void,
|
||||||
) {
|
) {
|
||||||
ob.write(Object {
|
unsafe {
|
||||||
next: core::ptr::null_mut(),
|
ob.write(Object {
|
||||||
tbase: tbase as _,
|
next: core::ptr::null_mut(),
|
||||||
dbase: dbase as _,
|
tbase: tbase as _,
|
||||||
table: Table::Multiple(begin as _),
|
dbase: dbase as _,
|
||||||
});
|
table: Table::Multiple(begin as _),
|
||||||
|
});
|
||||||
|
|
||||||
let mut guard = get_finder().inner.lock().unwrap();
|
let mut guard = get_finder().inner.lock().unwrap();
|
||||||
(*ob).next = guard.object;
|
(*ob).next = guard.object;
|
||||||
guard.object = ob;
|
guard.object = ob;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn __register_frame_info_table(begin: *const c_void, ob: *mut Object) {
|
unsafe extern "C" fn __register_frame_info_table(begin: *const c_void, ob: *mut Object) {
|
||||||
__register_frame_info_table_bases(begin, ob, core::ptr::null_mut(), core::ptr::null_mut());
|
unsafe {
|
||||||
|
__register_frame_info_table_bases(begin, ob, core::ptr::null_mut(), core::ptr::null_mut())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -161,37 +167,39 @@ unsafe extern "C" fn __register_frame_table(begin: *const c_void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let storage = Box::into_raw(Box::new(MaybeUninit::<Object>::uninit())) as *mut Object;
|
let storage = Box::into_raw(Box::new(MaybeUninit::<Object>::uninit())) as *mut Object;
|
||||||
__register_frame_info_table(begin, storage);
|
unsafe { __register_frame_info_table(begin, storage) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn __deregister_frame_info_bases(begin: *const c_void) -> *mut Object {
|
extern "C" fn __deregister_frame_info_bases(begin: *const c_void) -> *mut Object {
|
||||||
if begin.is_null() {
|
if begin.is_null() {
|
||||||
return core::ptr::null_mut();
|
return core::ptr::null_mut();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut guard = get_finder().inner.lock().unwrap();
|
let mut guard = get_finder().inner.lock().unwrap();
|
||||||
let mut prev = &mut guard.object;
|
unsafe {
|
||||||
let mut cur = *prev;
|
let mut prev = &mut guard.object;
|
||||||
|
let mut cur = *prev;
|
||||||
|
|
||||||
while !cur.is_null() {
|
while !cur.is_null() {
|
||||||
let found = match (*cur).table {
|
let found = match (*cur).table {
|
||||||
Table::Single(addr) => addr == begin,
|
Table::Single(addr) => addr == begin,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
if found {
|
if found {
|
||||||
*prev = (*cur).next;
|
*prev = (*cur).next;
|
||||||
return cur;
|
return cur;
|
||||||
|
}
|
||||||
|
prev = &mut (*cur).next;
|
||||||
|
cur = *prev;
|
||||||
}
|
}
|
||||||
prev = &mut (*cur).next;
|
|
||||||
cur = *prev;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
core::ptr::null_mut()
|
core::ptr::null_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn __deregister_frame_info(begin: *const c_void) -> *mut Object {
|
extern "C" fn __deregister_frame_info(begin: *const c_void) -> *mut Object {
|
||||||
__deregister_frame_info_bases(begin)
|
__deregister_frame_info_bases(begin)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,5 +209,5 @@ unsafe extern "C" fn __deregister_frame(begin: *const c_void) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let storage = __deregister_frame_info(begin);
|
let storage = __deregister_frame_info(begin);
|
||||||
drop(Box::from_raw(storage as *mut MaybeUninit<Object>))
|
drop(unsafe { Box::from_raw(storage as *mut MaybeUninit<Object>) })
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#![feature(c_unwind)]
|
#![feature(c_unwind)]
|
||||||
#![feature(naked_functions)]
|
#![feature(naked_functions)]
|
||||||
#![feature(asm)]
|
#![feature(asm)]
|
||||||
#![allow(unused_unsafe)]
|
#![warn(rust_2018_idioms)]
|
||||||
|
#![warn(unsafe_op_in_unsafe_fn)]
|
||||||
|
|
||||||
mod arch;
|
mod arch;
|
||||||
mod find_fde;
|
mod find_fde;
|
||||||
|
@ -7,12 +7,12 @@ pub unsafe fn get_unlimited_slice<'a>(start: *const u8) -> &'a [u8] {
|
|||||||
let start = start as usize;
|
let start = start as usize;
|
||||||
let end = start.saturating_add(isize::MAX as _);
|
let end = start.saturating_add(isize::MAX as _);
|
||||||
let len = end - start;
|
let len = end - start;
|
||||||
core::slice::from_raw_parts(start as *const _, len)
|
unsafe { core::slice::from_raw_parts(start as *const _, len) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn deref_pointer(ptr: Pointer) -> usize {
|
pub unsafe fn deref_pointer(ptr: Pointer) -> usize {
|
||||||
match ptr {
|
match ptr {
|
||||||
Pointer::Direct(x) => x as _,
|
Pointer::Direct(x) => x as _,
|
||||||
Pointer::Indirect(x) => *(x as *const _),
|
Pointer::Indirect(x) => unsafe { *(x as *const _) },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user