forked from M-Labs/nac3
Kernel: implemented KernelException
This commit is contained in:
parent
6f37128911
commit
e65d4e0e84
|
@ -189,6 +189,23 @@ async fn handle_run_kernel(stream: &TcpStream, control: &Rc<RefCell<kernel::Cont
|
||||||
write_header(stream, Reply::KernelFinished).await?;
|
write_header(stream, Reply::KernelFinished).await?;
|
||||||
break;
|
break;
|
||||||
},
|
},
|
||||||
|
kernel::Message::KernelException(exception, backtrace) => {
|
||||||
|
write_header(stream, Reply::KernelException).await?;
|
||||||
|
write_chunk(stream, exception.name.as_ref()).await?;
|
||||||
|
write_chunk(stream, exception.message.as_ref()).await?;
|
||||||
|
write_i64(stream, exception.param[0] as i64).await?;
|
||||||
|
write_i64(stream, exception.param[1] as i64).await?;
|
||||||
|
write_i64(stream, exception.param[2] as i64).await?;
|
||||||
|
write_chunk(stream, exception.file.as_ref()).await?;
|
||||||
|
write_i32(stream, exception.line as i32).await?;
|
||||||
|
write_i32(stream, exception.column as i32).await?;
|
||||||
|
write_chunk(stream, exception.function.as_ref()).await?;
|
||||||
|
write_i32(stream, backtrace.len() as i32).await?;
|
||||||
|
for &addr in backtrace {
|
||||||
|
write_i32(stream, addr as i32).await?;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
panic!("unexpected message from core1 while kernel was running: {:?}", reply);
|
panic!("unexpected message from core1 while kernel was running: {:?}", reply);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,21 @@ pub struct Exception<'a> {
|
||||||
pub param: [i64; 3]
|
pub param: [i64; 3]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn str_err(_: core::str::Utf8Error) -> core::fmt::Error {
|
||||||
|
core::fmt::Error
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> core::fmt::Debug for Exception<'a> {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
write!(f, "Exception {} from {} in {}:{}:{}, message: {}",
|
||||||
|
core::str::from_utf8(self.name.as_ref()).map_err(str_err)?,
|
||||||
|
core::str::from_utf8(self.function.as_ref()).map_err(str_err)?,
|
||||||
|
core::str::from_utf8(self.file.as_ref()).map_err(str_err)?,
|
||||||
|
self.line, self.column,
|
||||||
|
core::str::from_utf8(self.message.as_ref()).map_err(str_err)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const MAX_BACKTRACE_SIZE: usize = 128;
|
const MAX_BACKTRACE_SIZE: usize = 128;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -189,10 +204,16 @@ pub unsafe extern fn raise(exception: *const Exception) -> ! {
|
||||||
|
|
||||||
let result = uw::_Unwind_RaiseException(&mut INFLIGHT.uw_exception);
|
let result = uw::_Unwind_RaiseException(&mut INFLIGHT.uw_exception);
|
||||||
assert!(result == uw::_URC_END_OF_STACK);
|
assert!(result == uw::_URC_END_OF_STACK);
|
||||||
debug!("Result: {:?}", result);
|
|
||||||
|
|
||||||
INFLIGHT.backtrace_size = 0;
|
INFLIGHT.backtrace_size = 0;
|
||||||
unimplemented!("top level exception handling");
|
// read backtrace
|
||||||
|
let _ = uw::backtrace(|ip| {
|
||||||
|
if INFLIGHT.backtrace_size < MAX_BACKTRACE_SIZE {
|
||||||
|
INFLIGHT.backtrace[INFLIGHT.backtrace_size] = ip;
|
||||||
|
INFLIGHT.backtrace_size += 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
crate::kernel::terminate(INFLIGHT.exception.as_ref().unwrap(), INFLIGHT.backtrace[..INFLIGHT.backtrace_size].as_mut());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe extern fn reraise() -> ! {
|
pub unsafe extern fn reraise() -> ! {
|
||||||
|
|
|
@ -19,6 +19,7 @@ pub enum Message {
|
||||||
LoadFailed,
|
LoadFailed,
|
||||||
StartRequest,
|
StartRequest,
|
||||||
KernelFinished,
|
KernelFinished,
|
||||||
|
KernelException(&'static eh_artiq::Exception<'static>, &'static [usize]),
|
||||||
RpcSend { is_async: bool, data: Arc<Vec<u8>> },
|
RpcSend { is_async: bool, data: Arc<Vec<u8>> },
|
||||||
RpcRecvRequest(*mut ()),
|
RpcRecvRequest(*mut ()),
|
||||||
RpcRecvReply(Result<usize, ()>),
|
RpcRecvReply(Result<usize, ()>),
|
||||||
|
@ -82,6 +83,27 @@ extern fn rpc_send_async(service: u32, tag: &CSlice<u8>, data: *const *const ())
|
||||||
rpc_send_common(true, service, tag, data);
|
rpc_send_common(true, service, tag, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static mut KERNEL_LOAD_ADDR: usize = 0;
|
||||||
|
|
||||||
|
pub fn terminate(exception: &'static eh_artiq::Exception<'static>, backtrace: &'static mut [usize]) -> ! {
|
||||||
|
let load_addr = unsafe {
|
||||||
|
KERNEL_LOAD_ADDR
|
||||||
|
};
|
||||||
|
let mut cursor = 0;
|
||||||
|
// The address in the backtrace is relocated, so we have to convert it back to the address in
|
||||||
|
// the original python script, and remove those Rust function backtrace.
|
||||||
|
for i in 0..backtrace.len() {
|
||||||
|
if backtrace[i] >= load_addr {
|
||||||
|
backtrace[cursor] = backtrace[i] - load_addr;
|
||||||
|
cursor += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let core1_tx: &mut sync_channel::Sender<Message> = unsafe { mem::transmute(KERNEL_CHANNEL_1TO0) };
|
||||||
|
core1_tx.send(Message::KernelException(exception, &backtrace[..cursor]));
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn attribute_writeback(typeinfo: *const ()) {
|
unsafe fn attribute_writeback(typeinfo: *const ()) {
|
||||||
struct Attr {
|
struct Attr {
|
||||||
offset: usize,
|
offset: usize,
|
||||||
|
@ -299,6 +321,9 @@ pub fn main_core1() {
|
||||||
Message::LoadRequest(data) => {
|
Message::LoadRequest(data) => {
|
||||||
match dyld::load(&data, &resolve) {
|
match dyld::load(&data, &resolve) {
|
||||||
Ok(library) => {
|
Ok(library) => {
|
||||||
|
unsafe {
|
||||||
|
KERNEL_LOAD_ADDR = library.image.as_ptr() as usize;
|
||||||
|
}
|
||||||
let bss_start = library.lookup(b"__bss_start");
|
let bss_start = library.lookup(b"__bss_start");
|
||||||
let end = library.lookup(b"_end");
|
let end = library.lookup(b"_end");
|
||||||
if let Some(bss_start) = bss_start {
|
if let Some(bss_start) = bss_start {
|
||||||
|
|
|
@ -104,3 +104,23 @@ pub async fn write_i32(stream: &TcpStream, value: i32) -> Result<()> {
|
||||||
value as u8].iter().copied()).await?;
|
value as u8].iter().copied()).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn write_i64(stream: &TcpStream, value: i64) -> Result<()> {
|
||||||
|
stream.send([
|
||||||
|
(value >> 56) as u8,
|
||||||
|
(value >> 48) as u8,
|
||||||
|
(value >> 40) as u8,
|
||||||
|
(value >> 32) as u8,
|
||||||
|
(value >> 24) as u8,
|
||||||
|
(value >> 16) as u8,
|
||||||
|
(value >> 8) as u8,
|
||||||
|
value as u8].iter().copied()).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn write_chunk(stream: &TcpStream, value: &[u8]) -> Result<()> {
|
||||||
|
write_i32(stream, value.len() as i32).await?;
|
||||||
|
stream.send(value.iter().copied()).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue