From fd8b8eaacb2656c61022d66060b39887d3ba378e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ma=C3=ABlle=20MARTIN?= <maelle.martin@proton.me>
Date: Wed, 21 Aug 2024 18:22:05 +0200
Subject: [PATCH] SCRIPT: Fixed some segv

- Borrowing llvm context, don't dispose of it
- Didn't init all the needed things for the JIT
- Incorrect buffer size for the random generator
- Log what's happening in the temp/lock file thing
---
 src/Rust/.gitignore                        |  1 +
 src/Rust/vvs_llvm/src/bindings/context.rs  | 10 +++++++---
 src/Rust/vvs_llvm/src/bindings/function.rs |  2 +-
 src/Rust/vvs_llvm/src/bindings/module.rs   | 10 ++++++++++
 src/Rust/vvs_llvm/src/init.rs              |  6 ++++++
 src/Rust/vvs_runtime/src/jit.rs            | 11 +++--------
 src/Rust/vvs_utils/src/rand.rs             |  4 ++--
 src/Rust/vvs_xdg/src/file/lock.rs          | 23 ++++++++++++++--------
 src/Rust/vvs_xdg/src/file/temp.rs          |  1 +
 9 files changed, 46 insertions(+), 22 deletions(-)
 create mode 100644 src/Rust/.gitignore

diff --git a/src/Rust/.gitignore b/src/Rust/.gitignore
new file mode 100644
index 00000000..78fb1fce
--- /dev/null
+++ b/src/Rust/.gitignore
@@ -0,0 +1 @@
+.gdb_history
diff --git a/src/Rust/vvs_llvm/src/bindings/context.rs b/src/Rust/vvs_llvm/src/bindings/context.rs
index 88c01d3c..a9aadfcf 100644
--- a/src/Rust/vvs_llvm/src/bindings/context.rs
+++ b/src/Rust/vvs_llvm/src/bindings/context.rs
@@ -5,7 +5,9 @@ use std::{
     marker,
 };
 
-crate::bindings::declare! { mut LLVMContextRef as Context<'a> }
+crate::bindings::declare! { mut LLVMContextRef as Context<'a> {
+    borrowed: bool,
+} }
 
 macro_rules! get_type {
     ($llvm:ident as $name:ident) => {
@@ -32,7 +34,7 @@ impl Context<'_> {
             // aborted the program.
             log::debug!("{err}");
         }
-        Self { inner: unsafe { LLVMContextCreate() }, marker: marker::PhantomData }
+        Self { inner: unsafe { LLVMContextCreate() }, borrowed: false, marker: marker::PhantomData }
     }
 
     /// Create a new builder for this context.
@@ -60,6 +62,8 @@ impl Context<'_> {
 
 impl Drop for Context<'_> {
     fn drop(&mut self) {
-        unsafe { LLVMContextDispose(self.inner) }
+        if !self.borrowed {
+            unsafe { LLVMContextDispose(self.inner) }
+        }
     }
 }
diff --git a/src/Rust/vvs_llvm/src/bindings/function.rs b/src/Rust/vvs_llvm/src/bindings/function.rs
index 816d13eb..b12f0cca 100644
--- a/src/Rust/vvs_llvm/src/bindings/function.rs
+++ b/src/Rust/vvs_llvm/src/bindings/function.rs
@@ -63,7 +63,7 @@ impl<'a> Function<'a> {
 
     /// Get the LLVM context of the function.
     pub fn context(&'a self) -> Context<'a> {
-        unsafe { Context::from_ptr(LLVMGetTypeContext(LLVMTypeOf(self.inner))) }
+        unsafe { Context::from_ptr(LLVMGetTypeContext(LLVMTypeOf(self.inner)), true) }
     }
 
     /// Add a new basic block to the function and returns it.
diff --git a/src/Rust/vvs_llvm/src/bindings/module.rs b/src/Rust/vvs_llvm/src/bindings/module.rs
index b11a16c5..4b0f4c32 100644
--- a/src/Rust/vvs_llvm/src/bindings/module.rs
+++ b/src/Rust/vvs_llvm/src/bindings/module.rs
@@ -27,6 +27,16 @@ impl Module<'_> {
             ptr => Ok(unsafe { FunctionDeclaration::from_ptr(ptr) }),
         }
     }
+
+    /// Get the name of the module.
+    pub fn name(&self) -> &str {
+        let mut len = 0;
+        std::str::from_utf8(unsafe {
+            let c_ptr = LLVMGetModuleIdentifier(self.as_ptr(), &mut len);
+            std::slice::from_raw_parts(c_ptr as *const _, len)
+        })
+        .expect("valid utf8 module name")
+    }
 }
 
 impl Drop for Module<'_> {
diff --git a/src/Rust/vvs_llvm/src/init.rs b/src/Rust/vvs_llvm/src/init.rs
index dfff4b9a..56355ac9 100644
--- a/src/Rust/vvs_llvm/src/init.rs
+++ b/src/Rust/vvs_llvm/src/init.rs
@@ -28,7 +28,13 @@ pub fn initialize_llvm() -> anyhow::Result<()> {
     call_once()
         .then(|| unsafe {
             llvm_sys::target::LLVMInitializeX86Target();
+            llvm_sys::target::LLVMInitializeX86AsmParser();
+            llvm_sys::target::LLVMInitializeX86AsmPrinter();
+            llvm_sys::target::LLVMInitializeX86TargetInfo();
+            llvm_sys::target::LLVMInitializeX86TargetMC();
+            llvm_sys::target::LLVMInitializeX86Disassembler();
             print_llvm_infos();
+            log::debug!("llvm initialized for target x86_64");
         })
         .ok_or_else(|| anyhow!("llvm was already initialized for this executable!"))
 }
diff --git a/src/Rust/vvs_runtime/src/jit.rs b/src/Rust/vvs_runtime/src/jit.rs
index df58f4b6..e238daed 100644
--- a/src/Rust/vvs_runtime/src/jit.rs
+++ b/src/Rust/vvs_runtime/src/jit.rs
@@ -72,13 +72,7 @@ impl JIT {
         unsafe {
             // Create the jit.
             let mut jit = ptr::null_mut();
-            let mut tmb = ptr::null_mut();
-            llvm_expect!(LLVMOrcJITTargetMachineBuilderDetectHost(&mut tmb), "failed to create orc jit builder");
-
-            let jit_builder = LLVMOrcCreateLLJITBuilder();
-            LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(jit_builder, tmb);
-            llvm_expect!(LLVMOrcCreateLLJIT(&mut jit, jit_builder), "failed to create the orc jit");
-
+            llvm_expect!(LLVMOrcCreateLLJIT(&mut jit, ptr::null_mut()), "failed to create the orc jit");
             log::debug!("got data layout: {}", CStr::from_ptr(LLVMOrcLLJITGetDataLayoutStr(jit)).to_string_lossy());
 
             // Create things, in this order.
@@ -116,11 +110,12 @@ impl JIT {
     /// Get the context out of the JIT thingy. Used to create a LLVM module to be used latter by
     /// the JIT.
     pub fn ctx(&self) -> Context {
-        unsafe { Context::from_ptr(LLVMOrcThreadSafeContextGetContext(self.tsctx)) }
+        unsafe { Context::from_ptr(LLVMOrcThreadSafeContextGetContext(self.tsctx), true) }
     }
 
     /// Add a new module to the JIT engine.
     pub fn with_module(&self, module: Module) -> anyhow::Result<&Self> {
+        log::debug!("add module `{}` to jit engine", module.name());
         let tsm = unsafe { LLVMOrcCreateNewThreadSafeModule(module.as_ptr(), self.tsctx) };
         let rc = unsafe { LLVMOrcLLJITAddLLVMIRModule(self.jit, self.dylib, tsm) };
         unsafe { llvm_expect!(rc, "failed to add the module into the jit") };
diff --git a/src/Rust/vvs_utils/src/rand.rs b/src/Rust/vvs_utils/src/rand.rs
index 8b10f723..c49c4aee 100644
--- a/src/Rust/vvs_utils/src/rand.rs
+++ b/src/Rust/vvs_utils/src/rand.rs
@@ -5,7 +5,7 @@ use std::{cell::RefCell, sync::OnceLock};
 
 /// Simple Mersenne Twister (MT19937-64) implementation.
 struct MersenneTwister {
-    mt: [u64; MersenneTwister::W as usize],
+    mt: [u64; MersenneTwister::N as usize],
     index: usize,
 }
 
@@ -77,7 +77,7 @@ pub fn rand() -> u64 {
     MERSENNE.with(|mt| {
         mt.get_or_init(|| {
             let index = MersenneTwister::N as usize;
-            let mut mt = [0; MersenneTwister::W as usize];
+            let mut mt = [0; MersenneTwister::N as usize];
             mt[0] = get_seed();
             (1..MersenneTwister::N).for_each(|i| {
                 let index = i as usize - 1;
diff --git a/src/Rust/vvs_xdg/src/file/lock.rs b/src/Rust/vvs_xdg/src/file/lock.rs
index 4c563bcb..4c0fe27f 100644
--- a/src/Rust/vvs_xdg/src/file/lock.rs
+++ b/src/Rust/vvs_xdg/src/file/lock.rs
@@ -1,7 +1,7 @@
 use crate::*;
 use std::{
     collections::hash_map::DefaultHasher,
-    fs::{File, OpenOptions},
+    fs::{self, File, OpenOptions},
     hash::{Hash, Hasher},
     io::Error as IoError,
     path::Path,
@@ -25,7 +25,9 @@ pub enum LockError {
 pub type LockResult<T> = Result<T, LockError>;
 
 /// Structure used to hold the lock file for a resource that can be hashed.
-pub struct LockFile(File);
+pub struct LockFile {
+    path: PathBuf,
+}
 
 impl LockFile {
     #[inline]
@@ -51,12 +53,14 @@ impl LockFile {
             .map_err(Self::handle_xdg_error)?
         {
             MaybeFolderList::Empty => unreachable!("failed to find the runtime dir..."),
-            MaybeFolderList::Folder(f) | MaybeFolderList::Many(f, _) => Ok(Self(
-                OpenOptions::new()
+            MaybeFolderList::Folder(path) | MaybeFolderList::Many(path, _) => {
+                log::debug!("create lock file at: {}", path.display());
+                let _ = OpenOptions::new()
                     .create_new(true)
-                    .open(f)
-                    .map_err(Self::handle_io_error)?,
-            )),
+                    .open(&path)
+                    .map_err(Self::handle_io_error)?;
+                Ok(Self { path })
+            }
         }
     }
 
@@ -86,6 +90,9 @@ impl LockFile {
 impl Drop for LockFile {
     #[inline]
     fn drop(&mut self) {
-        todo!("drop {:?}", self.0)
+        match fs::remove_file(&self.path) {
+            Ok(_) => log::debug!("remove lock file: {}", self.path.display()),
+            Err(err) => log::error!("failed to remove lock file '{}': {err}", self.path.display()),
+        }
     }
 }
diff --git a/src/Rust/vvs_xdg/src/file/temp.rs b/src/Rust/vvs_xdg/src/file/temp.rs
index dc0d36a6..514d496f 100644
--- a/src/Rust/vvs_xdg/src/file/temp.rs
+++ b/src/Rust/vvs_xdg/src/file/temp.rs
@@ -121,6 +121,7 @@ impl TempFile {
     pub fn new(app: impl AsRef<str>) -> TempResult<Self> {
         let (pid, rand) = (std::process::id(), rand());
         let path = Self::create(app, format!("tmp.{pid}.{rand}"))?;
+        log::debug!("create temporary file at: {}", path.display());
         let file = OpenOptions::new()
             .create_new(true)
             .write(true)
-- 
GitLab