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?;
|
||||
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);
|
||||
}
|
||||
|
@ -38,6 +38,21 @@ pub struct Exception<'a> {
|
||||
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;
|
||||
|
||||
#[repr(C)]
|
||||
@ -189,10 +204,16 @@ pub unsafe extern fn raise(exception: *const Exception) -> ! {
|
||||
|
||||
let result = uw::_Unwind_RaiseException(&mut INFLIGHT.uw_exception);
|
||||
assert!(result == uw::_URC_END_OF_STACK);
|
||||
debug!("Result: {:?}", result);
|
||||
|
||||
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() -> ! {
|
||||
|
@ -19,6 +19,7 @@ pub enum Message {
|
||||
LoadFailed,
|
||||
StartRequest,
|
||||
KernelFinished,
|
||||
KernelException(&'static eh_artiq::Exception<'static>, &'static [usize]),
|
||||
RpcSend { is_async: bool, data: Arc<Vec<u8>> },
|
||||
RpcRecvRequest(*mut ()),
|
||||
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);
|
||||
}
|
||||
|
||||
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 ()) {
|
||||
struct Attr {
|
||||
offset: usize,
|
||||
@ -299,6 +321,9 @@ pub fn main_core1() {
|
||||
Message::LoadRequest(data) => {
|
||||
match dyld::load(&data, &resolve) {
|
||||
Ok(library) => {
|
||||
unsafe {
|
||||
KERNEL_LOAD_ADDR = library.image.as_ptr() as usize;
|
||||
}
|
||||
let bss_start = library.lookup(b"__bss_start");
|
||||
let end = library.lookup(b"_end");
|
||||
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?;
|
||||
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
Block a user