Remove useless libc, elf and ucontext, add comments to exceptions

improve propagation of errors in raise_exception
This commit is contained in:
Quentin Legot 2023-04-05 16:02:54 +02:00
parent 41611b54e8
commit 44cfb828fb
7 changed files with 95 additions and 258 deletions

7
Cargo.lock generated
View File

@ -7,7 +7,6 @@ name = "burritos"
version = "0.1.0"
dependencies = [
"cc",
"libc",
]
[[package]]
@ -15,9 +14,3 @@ name = "cc"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "libc"
version = "0.2.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"

View File

@ -3,9 +3,6 @@ name = "burritos"
version = "0.1.0"
edition = "2021"
[dependencies]
libc = { version = "0.2.139", features = ["extra_traits"] }
[registries.crates-io]
protocol = "sparse"

View File

@ -1,143 +0,0 @@
//Declaration des alias
/*
Def ELF :
The header file <elf.h> defines the format of ELF executable binary
files. Amongst these files are normal executable files, relocatable
object files, core files and shared libraries.
An executable file using the ELF file format consists of an ELF header,
followed by a program header table or a section header table, or both.
The ELF header is always at offset zero of the file. The program
header table and the section header table's offset in the file are
defined in the ELF header. The two tables describe the rest of the
particularities of the file
*/
/* Type for a 16-bit quantity. */
type Elf32_Half = u16;
type Elf64_Half = u16;
/* Types for signed and unsigned 32-bit quantities. */
type Elf32_Word = u32;
type Elf32_Sword = i32;
type Elf64_Word = u32;
type Elf64_Sword = i32;
/* Types for signed and unsigned 64-bit quantities. */
type Elf32_Xword = u64;
type Elf32_Sxword = i64;
type Elf64_Xword = u64;
type Elf64_Sxword = i64;
/* Type of addresses. */
type Elf32_Addr = u32;
type Elf64_Addr = u64;
/* Type of file offsets. */
type Elf32_Off = u32;
type Elf64_Off = u64;
//role de ce truc ?
const EI_NIDENT : u8 = 16;
//ELF file header 32 bits
struct Elf32Ehdr{
e_ident : [u8;EI_NIDENT],//16 octects décrivant comment le fichier doit etre parsé
//e_ident must starts with magice number : 0x 7f 45 4c 46
e_type : Elf32_Half,//type of the file
e_machine : Elf32_Half,//type architecture machine
e_version : Elf32_Word,//always 1
e_entry : Elf32_Addr,//entry point @ for executable
e_phoff : Elf32_Off,//Offset of the program header table
e_shoff : Elf32_Off,//Offset of the section header table
e_flags : Elf32_Word,//des flags ?
e_ehsize : Elf32_Half,//size of this (the header), redundant
e_phentsize : Elf32_Half,//size per program header
e_phnum : Elf32_Half,//number of program header
e_shentsize : Elf32_Half,//size per section header
e_shnum : Elf32_Half,//number of section header
e_shstrndx : Elf32_Half//section header string table index
}
//ELF file header 64 bits
//les champs ont le meme rôle que dans le header 32 bits
struct Elf64Ehdr{
e_ident : [u8;EI_NIDENT],
e_type : Elf64_Half,
e_machine : Elf64_Half,
e_version : Elf64_Word,
e_entry : Elf64_Addr,
e_phoff : Elf64_Off,
e_shoff : Elf64_Off,
e_flags : Elf64_Word,
e_ehsize : Elf64_Half,
e_phentsize : Elf64_Half,
e_phnum : Elf64_Half,
e_shentsize : Elf64_Half,
e_shnum : Elf64_Half,
e_shstrndx : Elf64_Half
}
/* e_ident offsets */
const EI_MAG0 : u32 = 0;
const EI_MAG1 : u32 = 1;
const EI_MAG2 : u32 = 2;
const EI_MAG3 : u32 = 3;
const EI_CLASS : u32 = 4;
const EI_DATA : u32 = 5;
const EI_VERSION : u32 = 6;
const EI_PAD : u32 = 7;
/* e_ident[EI_CLASS] */
const ELFCLASSNONE : u32 = 0;
const ELFCLASS32 : u32 = 1;
const ELFCLASS64 : u32 = 2;
/* e_ident[EI_DATA] */
const ELFDATANONE : u32 = 0;
const ELFDATA2LSB : u32 = 1;
const ELFDATA2MSB : u32 = 2;
/* e_type */
const ET_NONE : u32 = 0; /* No file type */
const ET_REL : u32 = 1; /* Relocatable file */
const ET_EXEC : u32 = 2; /* Executable file */
const ET_DYN : u32 = 3; /* Shared object file */
const ET_CORE : u32 = 4; /* Core file */
const ET_LOPROC : u32 = 0xff00; /* Processor-specific */
const ET_HIPROC : u32 = 0xffff; /* Processor-specific */
/* e_machine */
const EM_NONE : u32 = 0; /* No machine */
const EM_M32 : u32 = 1; /* AT&T WE 32100 */
const EM_SPARC : u32 = 2; /* SPARC */
const EM_386 : u32 = 3; /* Intel 80386 */
const EM_68K : u32 = 4; /* Motorola 68000 */
const EM_88K : u32 = 5; /* Motorola 88000 */
const EM_860 : u32 = 7; /* Intel 80860 */
const EM_MIPS : u32 = 8; /* MIPS R3000 */
const EM_RISC : u32 = 243; /* RISCV */
/* e_version */
const EV_NONE : u32 = 0; /* invalid version */
const EV_CURRENT : u32 = 1; /* current version */

View File

@ -4,41 +4,109 @@ use crate::simulator::{machine::{ExceptionType, Machine}, error::{MachineOk, Mac
use super::system::System;
/// The halt system call. Stops Burritos.
pub const SC_SHUTDOWN: u8 = 0;
/// The exit system call
///
/// Ends the calling thread
pub const SC_EXIT: u8 = 1;
/// The exec system call
///
/// Creates a new process (thread+address space)
pub const SC_EXEC: u8 = 2;
/// The join system call
///
/// Wait for the thread idThread to finish
pub const SC_JOIN: u8 = 3;
/// The create system call
///
/// Create a new file in nachos file system
pub const SC_CREATE: u8 = 4;
/// The open system call
///
/// Opens a file and returns an openfile identifier
pub const SC_OPEN: u8 = 5;
/// The read system call
///
/// Read in a file or the console
pub const SC_READ: u8 = 6;
/// The write system call
///
/// Write in a file or at the console
pub const SC_WRITE: u8 = 7;
/// Seek to a given position in an opened file
pub const SC_SEEK: u8 = 8;
/// The close system call
///
/// Close a file
pub const SC_CLOSE: u8 = 9;
/// The newThread system call
///
/// Create a new thread in the same address space
pub const SC_NEW_THREAD: u8 = 10;
pub const SC_YIELD: u8 = 11;
/// The Yield System call
///
/// Relinquish the CPU if any other thread is runnable
pub const SC_YIELD: u8 = 11;
/// the PError system call
///
/// print the last error message
pub const SC_PERROR: u8 = 12;
/// carry out P() on the semaphore
pub const SC_P: u8 = 13;
/// carry out V() on the semaphore
pub const SC_V: u8 = 14;
pub const SC_SEM_CREATE: u8 = 15 ;
/// create a semaphore and add it in g_objects_addrs
pub const SC_SEM_CREATE: u8 = 15;
/// destroy the semaphore corresponding to the id
pub const SC_SEM_DESTROY: u8 = 16;
pub const SC_LOCK_CREATE: u8 = 17 ;
pub const SC_LOCK_DESTROY: u8 = 18 ;
pub const SC_LOCK_ACQUIRE: u8 = 19 ;
pub const SC_LOCK_RELEASE: u8 = 20 ;
pub const SC_COND_CREATE: u8 = 21 ;
pub const SC_COND_DESTROY: u8 = 22 ;
pub const SC_COND_WAIT: u8 = 23 ;
/// create a lock and add it to g_object_addrs
pub const SC_LOCK_CREATE: u8 = 17;
/// destroy the lock corresponding to the id
pub const SC_LOCK_DESTROY: u8 = 18;
/// carry out acquire() on the lock
pub const SC_LOCK_ACQUIRE: u8 = 19;
/// carry out release() on the lock
pub const SC_LOCK_RELEASE: u8 = 20;
/// create a condition variable and add it to g_object_addrs
pub const SC_COND_CREATE: u8 = 21;
/// destroy the condition variable corresponding to the id
pub const SC_COND_DESTROY: u8 = 22;
/// carry out wait() on the condition
pub const SC_COND_WAIT: u8 = 23;
/// carry out signal() on the condition
pub const SC_COND_SIGNAL: u8 = 24;
/// carry out broadcast() on the condition
pub const SC_COND_BROADCAST: u8 = 25;
/// the TtySend system call
///
/// Sends some char by the serial line emulated
pub const SC_TTY_SEND: u8 = 26;
/// the TtyReceive system call
///
/// read some char on the serial line
pub const SC_TTY_RECEIVE: u8 = 27;
/// the Mkdir system call
///
/// make a new directory in the file system
pub const SC_MKDIR: u8 = 28;
/// the Rmdir system call
///
/// remove a directory from the file system
pub const SC_RMDIR: u8 = 29;
/// The Remove system call
///
/// Remove a file from the file system
pub const SC_REMOVE: u8 = 30;
/// The FSList system call
///
/// Lists all the file and directories in the filesystem
pub const SC_FSLIST: u8 = 31;
pub const SC_SYS_TIME: u8 = 32 ;
// The systime system call. Gets the system time
pub const SC_SYS_TIME: u8 = 32;
/// Map a file in memory
pub const SC_MMAP: u8 = 33;
/// Behaviour undefined and currently unused
pub const SC_DEBUG: u8 = 34;
pub const CONSOLE_OUTPUT: u8 = 1;
@ -47,15 +115,15 @@ pub const CONSOLE_OUTPUT: u8 = 1;
pub fn call(exception: &ExceptionType, machine: &mut Machine, system: &mut System) -> Result<MachineOk, MachineError> {
match exception {
ExceptionType::NoException => todo!(),
ExceptionType::NoException => Err("No Exception no yet implemented")?,
ExceptionType::SyscallException => syscall(machine, system),
ExceptionType::PagefaultException => todo!(),
ExceptionType::ReadOnlyException => todo!(),
ExceptionType::BusErrorException => todo!(),
ExceptionType::AddressErrorException => todo!(),
ExceptionType::OverflowException => todo!(),
ExceptionType::IllegalInstrException => todo!(),
ExceptionType::NumExceptionTypes => todo!(),
ExceptionType::PagefaultException => Err("Page Fault Exception not yet implemented")?,
ExceptionType::ReadOnlyException => Err("Read Only Exception not yet implemented")?,
ExceptionType::BusErrorException => Err("Bus Error Exception not yet implemented")?,
ExceptionType::AddressErrorException => Err("AddressErrorException not yet implemented")?,
ExceptionType::OverflowException => Err("OverflowException not yet implemented")?,
ExceptionType::IllegalInstrException => Err("IllegalInstrException not yet implemented")?,
ExceptionType::NumExceptionTypes => Err("NumExceptionTypes not yet implemented")?,
}
}
@ -92,11 +160,10 @@ fn syscall(machine: &mut Machine, system: &mut System) -> Result<MachineOk, Mach
if f as u8 == CONSOLE_OUTPUT {
println!("{}", buffer); // todo replace with console driver in the future
Ok(MachineOk::Ok)
} else {
todo!("SC_WRITE to file is not yet implemented")
Err("SC_WRITE to file is not yet implemented")?
}
Ok(MachineOk::Ok)
},
SC_SEEK => todo!(),
SC_CLOSE => todo!(),

View File

@ -2,7 +2,6 @@ pub mod process;
pub mod thread;
pub mod mgerror;
pub mod system;
mod ucontext;
mod synch;
mod thread_manager;
pub mod exception;

View File

@ -1,74 +0,0 @@
#[cfg(not(target_os = "windows"))]
use std::mem::MaybeUninit;
/// Safe wrapper for ucontext_t struct of linux-gnu libc
///
/// setcontext and getcontext are unsafe function, this wrap unsafe libc functions
///
/// This struct doesn't work on windows, because this struct is unavailable
///
/// todo ucontext_t is not thread-safe (doesn't implements Send and Sync trait), and cannot be use in Threads as rust require var in Mutex (see system.rs) to have everything inside to implements thread-safe traits
#[derive(PartialEq)]
pub struct UContextT {
#[cfg(not(target_os = "windows"))] // struct non disponible sur la libc sur windows
pub buf: libc::ucontext_t,
pub stack_bottom: Vec<i8>
}
#[cfg(not(target_os = "windows"))]
#[allow(unused)] // Temporary as we currently doesn't use this structure (this structure may disapear in a near future)
impl UContextT {
pub fn new() -> Self {
let mut context = MaybeUninit::<libc::ucontext_t>::uninit();
unsafe { libc::getcontext(context.as_mut_ptr()) };
Self {
buf: unsafe { context.assume_init() },
stack_bottom: Vec::default(),
}
}
/// Get user context and store it in variable pointed to by UCP.
///
/// Use `man getcontext` for more informations
pub fn get_context(&mut self) -> i32 {
unsafe {
libc::getcontext(&mut self.buf)
}
}
/// Set user context from information of variable pointed to by UCP.
///
/// Use `man setcontext` for more informations
pub fn set_context(&mut self) -> i32 {
unsafe {
libc::setcontext(&self.buf)
}
}
pub fn make_context(&mut self, func: extern "C" fn(), args: i32) {
unsafe {
libc::makecontext(&mut self.buf, func, args)
}
}
}
#[cfg(target_os = "windows")]
#[allow(unused)]
impl UContextT {
pub fn new() -> Self {
Self {
stack_bottom: Vec::default()
}
}
pub fn get_context(&mut self) {
// no op
}
pub fn set_context(&mut self) {
// no op
}
}

View File

@ -231,14 +231,12 @@ impl Machine {
self.set_status(MachineStatus::SystemMode);
// Handle the interruption
match exception::call(&exception, self, system) {
Ok(MachineOk::Shutdown) => {
Ok(r) => {
self.set_status(MachineStatus::UserMode);
return Ok(MachineOk::Shutdown);
}
_ => Err(format!("Syscall {:?} invalid or not implemented", exception))?
} // todo: return error if the syscall code is invalid
self.set_status(MachineStatus::UserMode);
Ok(MachineOk::Ok)
Ok(r)
},
Err(e) => Err(format!("Syscall {:?} invalid or not implemented", e))?
}
}
/// Execute the instructions table of a machine putted in param
@ -249,7 +247,7 @@ impl Machine {
pub fn run(&mut self, system: &mut System) {
loop {
match self.one_instruction(system) {
Ok(MachineOk::Ok) => println!("hello"),
Ok(MachineOk::Ok) => {},
Ok(MachineOk::Shutdown) => break,
Err(e) => panic!("FATAL at pc {} -> {}", self.pc, e)
}