diff --git a/.cargo/config.toml b/.cargo/config.toml deleted file mode 100644 index 88ee4ab91..000000000 --- a/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[env] -LLVM_SYS_170_PREFIX = { value = "lib/llvm", relative = true } diff --git a/.github/workflows/ci-linux.yml b/.github/workflows/ci-linux.yml index 921cf3ce8..df11d275b 100644 --- a/.github/workflows/ci-linux.yml +++ b/.github/workflows/ci-linux.yml @@ -29,8 +29,7 @@ jobs: run: | flatpak install --noninteractive flathub \ org.kde.Platform//6.6 org.kde.Sdk//6.6 \ - org.freedesktop.Sdk.Extension.rust-stable//23.08 \ - org.freedesktop.Sdk.Extension.llvm17//23.08 + org.freedesktop.Sdk.Extension.rust-stable//23.08 if: ${{ steps.flatpak-runtime.outputs.cache-hit != 'true' }} - name: Restore build files uses: actions/cache/restore@v4 diff --git a/.github/workflows/ci-mac.yml b/.github/workflows/ci-mac.yml index a05bd6072..d0161d1cd 100644 --- a/.github/workflows/ci-mac.yml +++ b/.github/workflows/ci-mac.yml @@ -4,50 +4,9 @@ on: env: CMAKE_BUILD_PARALLEL_LEVEL: '3' jobs: - llvm: - name: LLVM for Mac - runs-on: macos-12 - outputs: - dist-key: ${{ steps.cache-keys.outputs.dist }} - env: - LLVM_URL: https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.5/llvm-project-17.0.5.src.tar.xz - steps: - - name: Generate cache keys - run: | - hash=$(md5 -qs "$LLVM_URL") - echo "dist=${{ runner.os }}-llvm-$hash" >> $GITHUB_OUTPUT - id: cache-keys - - name: Check cached artifacts - uses: actions/cache/restore@v4 - with: - path: lib/llvm - key: ${{ steps.cache-keys.outputs.dist }} - lookup-only: true - id: cache - - name: Download LLVM - run: | - curl -Lo llvm.tar.xz "$LLVM_URL" - tar -xJ --strip-components=1 -f llvm.tar.xz - if: ${{ steps.cache.outputs.cache-hit != 'true' }} - - name: Run CMake - run: cmake --install-prefix ${{ github.workspace }}/lib/llvm -Wno-dev -DCMAKE_BUILD_TYPE:STRING=Release -DLLVM_ENABLE_ZSTD:BOOL=OFF -DLLVM_APPEND_VC_REV:BOOL=OFF -DLLVM_TARGETS_TO_BUILD:STRING=X86 -B build llvm - if: ${{ steps.cache.outputs.cache-hit != 'true' }} - - name: Build - run: cmake --build build --config Release - if: ${{ steps.cache.outputs.cache-hit != 'true' }} - - name: Export artifacts - run: cmake --install build --config Release - if: ${{ steps.cache.outputs.cache-hit != 'true' }} - - name: Cache artifacts - uses: actions/cache/save@v4 - with: - path: lib/llvm - key: ${{ steps.cache-keys.outputs.dist }} - if: ${{ steps.cache.outputs.cache-hit != 'true' }} build: name: Mac runs-on: macos-12 - needs: llvm env: CMAKE_PREFIX_PATH: qt/6.6.0/macos QT_URL_BASE: https://download.qt.io/online/qtsdkrepository/mac_x64/desktop/qt6_660/qt.qt6.660.clang_64/6.6.0-0-202310040910qtbase-MacOS-MacOS_12-Clang-MacOS-MacOS_12-X86_64-ARM64.7z @@ -55,12 +14,6 @@ jobs: steps: - name: Checkout source uses: actions/checkout@v4 - - name: Download LLVM - uses: actions/cache/restore@v4 - with: - path: lib/llvm - key: ${{ needs.llvm.outputs.dist-key }} - fail-on-cache-miss: true - name: Generate cache keys run: | require Digest::MD5; @@ -104,7 +57,7 @@ jobs: - name: Update Rust run: rustup update stable - name: Run CMake - run: cmake -DOB_BUILD_LLVM:BOOL=OFF --preset mac-release . + run: cmake --preset mac-release . - name: Build run: cmake --build --preset mac-release - name: Run tests diff --git a/.github/workflows/ci-windows.yml b/.github/workflows/ci-windows.yml index 138b09e8f..058cb8190 100644 --- a/.github/workflows/ci-windows.yml +++ b/.github/workflows/ci-windows.yml @@ -2,65 +2,14 @@ name: CI (Windows) on: workflow_call: env: - CMAKE_BUILD_PARALLEL_LEVEL: '2' + CMAKE_BUILD_PARALLEL_LEVEL: '4' jobs: - llvm: - name: LLVM for Windows - runs-on: windows-2022 - outputs: - dist-key: ${{ steps.cache-keys.outputs.dist }} - steps: - - name: Hash LLVM URL - run: | - $url = "https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.5/llvm-project-17.0.5.src.tar.xz" - $urlhash = [System.BitConverter]::ToString([System.Security.Cryptography.SHA256]::Create().ComputeHash([System.Text.Encoding]::UTF8.GetBytes($url))).Replace("-", "").ToLower() - echo "llvmurl=$url" >> $env:GITHUB_OUTPUT - echo "hash=$urlhash" >> $env:GITHUB_OUTPUT - id: download - - name: Generate cache keys - run: echo "dist=${{ runner.os }}-llvm-${{ steps.download.outputs.hash }}" >> $env:GITHUB_OUTPUT - id: cache-keys - - name: Check cached artifacts - uses: actions/cache/restore@v4 - with: - path: lib/llvm - key: ${{ steps.cache-keys.outputs.dist }} - lookup-only: true - id: cache - - name: Download LLVM - run: | - Invoke-WebRequest -Uri ${{ steps.download.outputs.llvmurl }} -OutFile llvm.tar.xz - unxz llvm.tar.xz - tar -x --strip-components=1 -f llvm.tar - if: ${{ steps.cache.outputs.cache-hit != 'true' }} - - name: Run CMake - run: cmake --install-prefix ${{ github.workspace }}/lib/llvm -Wno-dev -DLLVM_ENABLE_ZSTD:BOOL=OFF -DLLVM_APPEND_VC_REV:BOOL=OFF -DLLVM_TARGETS_TO_BUILD:STRING=X86 -B build llvm - if: ${{ steps.cache.outputs.cache-hit != 'true' }} - - name: Build - run: cmake --build build --config Release - if: ${{ steps.cache.outputs.cache-hit != 'true' }} - - name: Export artifacts - run: cmake --install build --config Release - if: ${{ steps.cache.outputs.cache-hit != 'true' }} - - name: Cache artifacts - uses: actions/cache/save@v4 - with: - path: lib/llvm - key: ${{ steps.cache-keys.outputs.dist }} - if: ${{ steps.cache.outputs.cache-hit != 'true' }} build: name: Windows runs-on: windows-2022 - needs: llvm steps: - name: Checkout source uses: actions/checkout@v4 - - name: Download LLVM - uses: actions/cache/restore@v4 - with: - path: lib/llvm - key: ${{ needs.llvm.outputs.dist-key }} - fail-on-cache-miss: true - name: Generate cache keys run: | echo "cargo=${{ runner.os }}-cargo" >> $env:GITHUB_OUTPUT @@ -100,7 +49,7 @@ jobs: - name: Update Rust run: rustup update stable - name: Run CMake - run: cmake -DOB_BUILD_LLVM:BOOL=OFF --preset windows-release . + run: cmake --preset windows-release . - name: Build run: cmake --build --preset windows-release - name: Run tests diff --git a/.gitignore b/.gitignore index 5f633c258..d03f3d868 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,5 @@ /.flatpak-builder/ /.kernel-debug /build/ -/lib/ /src/target/ Cargo.lock diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f34b8049..9e5b8c759 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,9 +2,6 @@ cmake_minimum_required(VERSION 3.21) project(obliteration) -# Project options. -option(OB_BUILD_LLVM "Download and build the LLVM from source." ON) - # Set warning level to highest. This will propagate to sub-directories too. if(WIN32) add_compile_options(/W4) diff --git a/README.md b/README.md index 71c6c04f3..91c67f832 100644 --- a/README.md +++ b/README.md @@ -28,12 +28,11 @@ We have a Discord server for discussion about Obliteration and its development. - [x] Built-in PKG file supports for Fake PKG. - [x] Game library. - [x] Emulate system calls instead of user-space libraries. -- [ ] Supports AArch64 CPU. ## System requirements - Windows 10, Linux or macOS 11+. -- x86-64 CPU. +- x86-64 CPU. We want to support non-x86 but currently we don't have any developers who are willing to work on this. - A jailbroken PS4 with FTP server that supports SELF decryption. ### Windows-specific requirements @@ -53,8 +52,6 @@ Obliteration supports only 4KB/8KB/16KB pages. Most people should not have any p - Rust on the latest stable channel - CMake 3.21+ - Make sure you have `Add CMake to the system PATH` selected when installing -- Python 3.6+ - - Make sure you have `Add python.exe to PATH` selected when installing ### Linux prerequisites diff --git a/flatpak.yml b/flatpak.yml index d245b9c1e..9460f22e8 100644 --- a/flatpak.yml +++ b/flatpak.yml @@ -6,13 +6,10 @@ platform-extensions: - org.freedesktop.Platform.GL.default sdk: org.kde.Sdk sdk-extensions: -- org.freedesktop.Sdk.Extension.llvm17 - org.freedesktop.Sdk.Extension.rust-stable command: obliteration build-options: append-path: /usr/lib/sdk/rust-stable/bin - env: - LLVM_SYS_170_PREFIX: /usr/lib/sdk/llvm17 build-args: - --share=network - --device=kvm # required for running tests @@ -27,14 +24,12 @@ finish-args: - --socket=pulseaudio modules: - name: obliteration - buildsystem: simple # cmake does not work somehow + buildsystem: simple build-commands: - - cmake -DOB_BUILD_LLVM:BOOL=OFF --preset linux-release . + - cmake --preset linux-release . - cmake --build --preset linux-release - cargo test --manifest-path src/Cargo.toml --workspace --exclude core - cmake --install build --prefix "$FLATPAK_DEST" - - mkdir -pv "$FLATPAK_DEST/lib" - - cp -v /usr/lib/sdk/llvm17/lib/libLLVM-17.so "$FLATPAK_DEST/lib" sources: - type: dir path: . diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1adaf2d38..11b031940 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,39 +5,6 @@ include(ExternalProject) find_package(Qt6 COMPONENTS Widgets REQUIRED) find_package(Threads REQUIRED) -# Setup LLVM target. -set(LLVM_OPTS -DCMAKE_INSTALL_PREFIX:STRING= -DLLVM_ENABLE_ZSTD:BOOL=OFF -DLLVM_APPEND_VC_REV:BOOL=OFF) - -if(WIN32) - if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64") - list(APPEND LLVM_OPTS -DLLVM_TARGETS_TO_BUILD:STRING=X86) - else() - message(FATAL_ERROR "Target CPU is not supported") - endif() -else() - if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64") - list(APPEND LLVM_OPTS -DLLVM_TARGETS_TO_BUILD:STRING=X86) - elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm64") - list(APPEND LLVM_OPTS -DLLVM_TARGETS_TO_BUILD:STRING=AArch64) - else() - message(FATAL_ERROR "Target CPU is not supported") - endif() - - list(APPEND LLVM_OPTS -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}) -endif() - -if(OB_BUILD_LLVM) - ExternalProject_Add(llvm - URL https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.5/llvm-project-17.0.5.src.tar.xz - URL_HASH SHA256=95d7eff82945cf05c16a1851d7b391fc2da726b87c1138125e3b6e4d300ab834 - DOWNLOAD_NO_PROGRESS true - CMAKE_ARGS -Wno-dev - CMAKE_CACHE_ARGS ${LLVM_OPTS} - SOURCE_SUBDIR llvm - BUILD_ALWAYS ON - INSTALL_DIR ${CMAKE_SOURCE_DIR}/lib/llvm) -endif() - # Setup Rust target. set(RUST_OUTPUTS $,${CMAKE_CURRENT_SOURCE_DIR}/target/debug,${CMAKE_CURRENT_SOURCE_DIR}/target/release>) set(KERNEL ${RUST_OUTPUTS}/obkrnl${CMAKE_EXECUTABLE_SUFFIX}) @@ -52,10 +19,6 @@ add_custom_target(core COMMAND cargo build $,--profile=dev,--release> WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -if(OB_BUILD_LLVM) - add_dependencies(core llvm) -endif() - # Setup application target. add_executable(obliteration WIN32 MACOSX_BUNDLE ansi_escape.cpp diff --git a/src/kernel/Cargo.toml b/src/kernel/Cargo.toml index e704c2be1..12b5a065f 100644 --- a/src/kernel/Cargo.toml +++ b/src/kernel/Cargo.toml @@ -19,7 +19,6 @@ hv = { path = "../hv" } iced-x86 = { version = "1.18", features = ["code_asm"] } libc = "0.2" llt = { path = "../llt" } -llvm-sys = { version = "170.0.0", features = ["strict-versioning", "prefer-static"] } macros = { path = "../macros" } param = { path = "../param" } serde = { version = "1.0", features = ["derive"] } diff --git a/src/kernel/src/ee/llvm/codegen.rs b/src/kernel/src/ee/llvm/codegen.rs deleted file mode 100644 index 154241f50..000000000 --- a/src/kernel/src/ee/llvm/codegen.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::llvm::module::LlvmModule; -use thiserror::Error; - -/// Contains states for lifting a module. -pub(super) struct Codegen<'a> { - output: &'a mut LlvmModule, -} - -impl<'a> Codegen<'a> { - pub fn new(output: &'a mut LlvmModule) -> Self { - Self { output } - } - - pub fn lift(&mut self, _offset: usize) -> Result<(), LiftError> { - Ok(()) - } -} - -/// Represents an error for [`Codegen::lift()`]. -#[derive(Debug, Error)] -pub enum LiftError {} diff --git a/src/kernel/src/ee/llvm/mod.rs b/src/kernel/src/ee/llvm/mod.rs deleted file mode 100644 index 1c53335d8..000000000 --- a/src/kernel/src/ee/llvm/mod.rs +++ /dev/null @@ -1,108 +0,0 @@ -use self::codegen::Codegen; -use super::ExecutionEngine; -use crate::fs::VPathBuf; -use crate::llvm::Llvm; -use crate::rtld::Module; -use crate::syscalls::Syscalls; -use std::sync::Arc; -use thiserror::Error; - -mod codegen; - -/// An implementation of [`ExecutionEngine`] using JIT powered by LLVM IR. -#[derive(Debug)] -pub struct LlvmEngine { - llvm: Arc, -} - -impl LlvmEngine { - pub fn new(llvm: &Arc) -> Arc { - Arc::new(Self { llvm: llvm.clone() }) - } - - fn lift( - &self, - module: &Module, - ) -> Result { - // Get a list of public functions. - let path = module.path(); - let targets = match module.entry() { - Some(v) => vec![v], - None => Vec::new(), - }; - - // Lift the public functions. - let mut lifting = self.llvm.create_module(path); - let mut codegen = Codegen::new(&mut lifting); - - for &addr in &targets { - if let Err(e) = codegen.lift(addr) { - return Err(LiftError::LiftingFailed(path.to_owned(), addr, e)); - } - } - - drop(codegen); - - // Create LLVM execution engine. - let lifted = match lifting.create_execution_engine() { - Ok(v) => v, - Err(e) => return Err(LiftError::CreateExecutionEngineFailed(path.to_owned(), e)), - }; - - Ok(lifted) - } -} - -impl ExecutionEngine for LlvmEngine { - type RawFn = RawFn; - type SetupModuleErr = SetupModuleError; - type GetFunctionErr = GetFunctionError; - - fn set_syscalls(&self, v: Syscalls) { - todo!() - } - - fn setup_module(self: &Arc, md: &mut Module) -> Result<(), Self::SetupModuleErr> { - todo!() - } - - unsafe fn get_function( - self: &Arc, - md: &Arc>, - addr: usize, - ) -> Result, Self::GetFunctionErr> { - todo!() - } -} - -/// An implementation of [`ExecutionEngine::RawFn`]. -#[derive(Debug)] -pub struct RawFn {} - -impl super::RawFn for RawFn { - fn addr(&self) -> usize { - todo!() - } - - unsafe fn exec1(&self, a: A) -> R { - todo!() - } -} - -/// An implementation of [`ExecutionEngine::SetupModuleErr`]. -#[derive(Debug, Error)] -pub enum SetupModuleError {} - -/// An implementation of [`ExecutionEngine::GetFunctionErr`]. -#[derive(Debug, Error)] -pub enum GetFunctionError {} - -/// Represents an error when module lifting is failed. -#[derive(Debug, Error)] -enum LiftError { - #[error("cannot lift function {1:#018x} on {0}")] - LiftingFailed(VPathBuf, usize, #[source] self::codegen::LiftError), - - #[error("cannot create LLVM execution engine for {0}")] - CreateExecutionEngineFailed(VPathBuf, #[source] crate::llvm::Error), -} diff --git a/src/kernel/src/ee/mod.rs b/src/kernel/src/ee/mod.rs index e4deaf1af..9afcc1745 100644 --- a/src/kernel/src/ee/mod.rs +++ b/src/kernel/src/ee/mod.rs @@ -3,53 +3,20 @@ use crate::memory::MemoryManager; use crate::process::ResourceType; use crate::process::VProc; use crate::rtld::Module; -use crate::syscalls::Syscalls; -use std::error::Error; use std::ffi::CString; -use std::fmt::Debug; use std::marker::PhantomPinned; use std::mem::size_of_val; use std::pin::Pin; use std::sync::Arc; -pub mod llvm; #[cfg(target_arch = "x86_64")] pub mod native; -/// An object to execute the PS4 binary. -pub trait ExecutionEngine: Debug + Send + Sync + 'static { - type RawFn: RawFn; - type SetupModuleErr: Error; - type GetFunctionErr: Error; - - /// # Panics - /// If this method called a second time. - fn set_syscalls(&self, v: Syscalls); - - fn setup_module(self: &Arc, md: &mut Module) -> Result<(), Self::SetupModuleErr>; - - unsafe fn get_function( - self: &Arc, - md: &Arc>, - addr: usize, - ) -> Result, Self::GetFunctionErr>; -} - -/// A function that was produced by [`ExecutionEngine`]. -pub trait RawFn: Debug + Send + Sync + 'static { - /// Returns address of this function in the memory. - fn addr(&self) -> usize; - - /// # Safety - /// The provided signature must be matched with the underlying function. - unsafe fn exec1(&self, a: A) -> R; -} - /// Encapsulate an argument of the PS4 entry point. -pub struct EntryArg { +pub struct EntryArg { vp: Arc, mm: Arc, - app: Arc>, + app: Arc, name: CString, path: CString, canary: [u8; 64], @@ -58,8 +25,8 @@ pub struct EntryArg { _pin: PhantomPinned, } -impl EntryArg { - pub fn new(vp: &Arc, mm: &Arc, app: Arc>) -> Self { +impl EntryArg { + pub fn new(vp: &Arc, mm: &Arc, app: Arc) -> Self { let path = app.path(); let name = CString::new(path.file_name().unwrap()).unwrap(); let path = CString::new(path.as_str()).unwrap(); diff --git a/src/kernel/src/ee/native/mod.rs b/src/kernel/src/ee/native/mod.rs index 5a752430c..9e3fbc016 100644 --- a/src/kernel/src/ee/native/mod.rs +++ b/src/kernel/src/ee/native/mod.rs @@ -1,4 +1,3 @@ -use super::ExecutionEngine; use crate::fs::{VPath, VPathBuf}; use crate::memory::Protections; use crate::process::VThread; @@ -38,10 +37,27 @@ impl NativeEngine { }) } - fn patch_mod(self: &Arc, module: &mut Module) -> Result - where - E: ExecutionEngine, - { + pub fn set_syscalls(&self, v: Syscalls) { + self.syscalls.set(v).unwrap(); + } + + pub fn setup_module(self: &Arc, md: &mut Module) -> Result<(), SetupModuleError> { + self.patch_mod(md)?; + Ok(()) + } + + pub unsafe fn get_function( + self: &Arc, + md: &Arc, + addr: usize, + ) -> Result, GetFunctionError> { + Ok(Arc::new(RawFn { + md: md.clone(), + addr, + })) + } + + fn patch_mod(self: &Arc, module: &mut Module) -> Result { let path = module.path(); // Patch all executable sections. @@ -648,33 +664,7 @@ impl NativeEngine { } } -impl ExecutionEngine for NativeEngine { - type RawFn = RawFn; - type SetupModuleErr = SetupModuleError; - type GetFunctionErr = GetFunctionError; - - fn set_syscalls(&self, v: Syscalls) { - self.syscalls.set(v).unwrap(); - } - - fn setup_module(self: &Arc, md: &mut Module) -> Result<(), Self::SetupModuleErr> { - self.patch_mod(md)?; - Ok(()) - } - - unsafe fn get_function( - self: &Arc, - md: &Arc>, - addr: usize, - ) -> Result, Self::GetFunctionErr> { - Ok(Arc::new(RawFn { - md: md.clone(), - addr, - })) - } -} - -/// An implementation of [`super::RawFn`]. +/// Raw executable function. #[derive(Debug)] pub struct RawFn { #[allow(unused)] @@ -682,12 +672,12 @@ pub struct RawFn { addr: usize, } -impl super::RawFn for RawFn { - fn addr(&self) -> usize { +impl RawFn { + pub fn addr(&self) -> usize { self.addr } - unsafe fn exec1(&self, a: A) -> R { + pub unsafe fn exec1(&self, a: A) -> R { let f: unsafe extern "sysv64" fn(A) -> R = transmute(self.addr); f(a) } diff --git a/src/kernel/src/llvm/mod.rs b/src/kernel/src/llvm/mod.rs deleted file mode 100644 index dec04dbd2..000000000 --- a/src/kernel/src/llvm/mod.rs +++ /dev/null @@ -1,78 +0,0 @@ -use self::module::LlvmModule; -use llvm_sys::core::{LLVMContextCreate, LLVMContextDispose, LLVMModuleCreateWithNameInContext}; -use llvm_sys::prelude::LLVMContextRef; -use std::ffi::{c_char, CStr, CString}; -use std::fmt::Display; -use std::sync::{Arc, Mutex}; - -pub mod module; - -/// A LLVM wrapper for thread-safe. -#[derive(Debug)] -pub struct Llvm { - context: Mutex, -} - -impl Llvm { - pub fn new() -> Arc { - let context = unsafe { LLVMContextCreate() }; - - Arc::new(Self { - context: Mutex::new(context), - }) - } - - pub fn create_module(self: &Arc, name: &str) -> LlvmModule { - let context = self.context.lock().unwrap(); - let name = CString::new(name).unwrap(); - let module = unsafe { LLVMModuleCreateWithNameInContext(name.as_ptr(), *context) }; - - LlvmModule::new(self, module) - } - - fn with_context(&self, f: F) -> R - where - F: FnOnce(LLVMContextRef) -> R, - { - f(*self.context.lock().unwrap()) - } -} - -impl Drop for Llvm { - fn drop(&mut self) { - unsafe { LLVMContextDispose(*self.context.get_mut().unwrap()) }; - } -} - -unsafe impl Send for Llvm {} -unsafe impl Sync for Llvm {} - -/// A wrapper on LLVM error. -#[derive(Debug)] -pub struct Error { - message: String, -} - -impl Error { - /// # Safety - /// `message` must be pointed to a null-terminated string allocated with `malloc` or a - /// compatible funtion because this method will free it with `free`. - unsafe fn new(message: *mut c_char) -> Self { - let owned = CStr::from_ptr(message) - .to_string_lossy() - .trim_end_matches('.') - .to_owned(); - - libc::free(message as _); - - Self { message: owned } - } -} - -impl Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(&self.message) - } -} - -impl std::error::Error for Error {} diff --git a/src/kernel/src/llvm/module.rs b/src/kernel/src/llvm/module.rs deleted file mode 100644 index a12152329..000000000 --- a/src/kernel/src/llvm/module.rs +++ /dev/null @@ -1,70 +0,0 @@ -use super::{Error, Llvm}; -use llvm_sys::core::LLVMDisposeModule; -use llvm_sys::execution_engine::{ - LLVMCreateExecutionEngineForModule, LLVMDisposeExecutionEngine, LLVMExecutionEngineRef, -}; -use llvm_sys::prelude::LLVMModuleRef; -use std::ffi::c_char; -use std::ptr::null_mut; -use std::sync::Arc; - -/// A wrapper on LLVM module for thread-safe. -pub struct LlvmModule { - llvm: Arc, - module: LLVMModuleRef, -} - -impl LlvmModule { - pub(super) fn new(llvm: &Arc, module: LLVMModuleRef) -> Self { - Self { - llvm: llvm.clone(), - module, - } - } - - pub fn create_execution_engine(mut self) -> Result { - let mut ee: LLVMExecutionEngineRef = null_mut(); - let module = self.module; - let mut error: *mut c_char = null_mut(); - - self.module = null_mut(); - - if self.llvm.with_context(|_| unsafe { - LLVMCreateExecutionEngineForModule(&mut ee, module, &mut error) - }) != 0 - { - return Err(unsafe { Error::new(error) }); - } - - Ok(ExecutionEngine { - llvm: self.llvm.clone(), - ee, - }) - } -} - -impl Drop for LlvmModule { - fn drop(&mut self) { - let m = self.module; - - if !m.is_null() { - self.llvm.with_context(|_| unsafe { LLVMDisposeModule(m) }); - } - } -} - -/// A wrapper on LLVM Execution Engine for thread-safe. -/// -/// # Safety -/// All JITed functions from this EE must not invoked once this EE has been droped. -pub struct ExecutionEngine { - llvm: Arc, - ee: LLVMExecutionEngineRef, -} - -impl Drop for ExecutionEngine { - fn drop(&mut self) { - self.llvm - .with_context(|_| unsafe { LLVMDisposeExecutionEngine(self.ee) }); - } -} diff --git a/src/kernel/src/main.rs b/src/kernel/src/main.rs index 89b03f6a6..d58cf1d12 100644 --- a/src/kernel/src/main.rs +++ b/src/kernel/src/main.rs @@ -2,11 +2,11 @@ use crate::arch::MachDep; use crate::budget::{Budget, BudgetManager, ProcType}; use crate::debug::{DebugManager, DebugManagerInitError}; use crate::dmem::DmemManager; -use crate::ee::{EntryArg, RawFn}; +use crate::ee::native::NativeEngine; +use crate::ee::EntryArg; use crate::errno::EEXIST; use crate::fs::{Fs, FsInitError, MkdirError, MountError, MountFlags, MountOpts, VPathBuf}; use crate::kqueue::KernelQueueManager; -use crate::llvm::Llvm; use crate::log::{print, LOGGER}; use crate::memory::{MemoryManager, MemoryManagerError}; use crate::namedobj::NamedObjManager; @@ -22,7 +22,7 @@ use crate::time::TimeManager; use crate::tty::{TtyInitError, TtyManager}; use crate::ucred::{AuthAttrs, AuthCaps, AuthInfo, AuthPaid, Gid, Ucred, Uid}; use crate::umtx::UmtxManager; -use clap::{Parser, ValueEnum}; +use clap::Parser; use llt::{OsThread, SpawnError}; use macros::vpath; use param::Param; @@ -47,7 +47,6 @@ mod errno; mod fs; mod idt; mod kqueue; -mod llvm; mod log; mod memory; mod namedobj; @@ -66,10 +65,10 @@ mod ucred; mod umtx; fn main() -> Exit { - start().into() + run().into() } -fn start() -> Result<(), KernelError> { +fn run() -> Result<(), KernelError> { // Begin logger. log::init(); @@ -189,7 +188,6 @@ fn start() -> Result<(), KernelError> { )); // Initialize foundations. - let llvm = Llvm::new(); let mut syscalls = Syscalls::new(); let fs = Fs::new(args.system, &cred, &mut syscalls)?; @@ -329,47 +327,6 @@ fn start() -> Result<(), KernelError> { print(log); - // Select execution engine. - match args.execution_engine.unwrap_or_default() { - #[cfg(target_arch = "x86_64")] - ExecutionEngine::Native => run( - args.debug_dump, - ¶m, - auth, - syscalls, - &fs, - &mm, - crate::ee::native::NativeEngine::new(), - root, - ), - #[cfg(not(target_arch = "x86_64"))] - ExecutionEngine::Native => { - error!("Native execution engine cannot be used on your machine."); - Err(KernelError::NativeExecutionEngineNotSupported) - } - ExecutionEngine::Llvm => run( - args.debug_dump, - ¶m, - auth, - syscalls, - &fs, - &mm, - crate::ee::llvm::LlvmEngine::new(&llvm), - root, - ), - } -} - -fn run( - dump: Option, - param: &Arc, - auth: AuthInfo, - mut syscalls: Syscalls, - fs: &Arc, - mm: &Arc, - ee: Arc, - root: VPathBuf, -) -> Result<(), KernelError> { // Initialize TTY system. #[allow(unused_variables)] // TODO: Remove this when someone use tty. let tty = TtyManager::new()?; @@ -381,9 +338,9 @@ fn run( let machdep = MachDep::new(&mut syscalls); let budget = BudgetManager::new(&mut syscalls); - DmemManager::new(fs, &mut syscalls); - SharedMemoryManager::new(mm, &mut syscalls); - Sysctl::new(mm, &machdep, &mut syscalls); + DmemManager::new(&fs, &mut syscalls); + SharedMemoryManager::new(&mm, &mut syscalls); + Sysctl::new(&mm, &machdep, &mut syscalls); TimeManager::new(&mut syscalls); KernelQueueManager::new(&mut syscalls); NetManager::new(&mut syscalls); @@ -408,7 +365,8 @@ fn run( // Initialize runtime linker. info!("Initializing runtime linker."); - let ld = RuntimeLinker::new(fs, mm, &ee, &mut syscalls, dump.as_deref()) + let ee = NativeEngine::new(); + let ld = RuntimeLinker::new(&fs, &mm, &ee, &mut syscalls, args.debug_dump.as_deref()) .map_err(|e| KernelError::RuntimeLinkerInitFailed(e.into()))?; ee.set_syscalls(syscalls); @@ -462,7 +420,7 @@ fn run( // Get entry point. let boot = ld.kernel().unwrap(); - let mut arg = Box::pin(EntryArg::::new(&proc, mm, app.clone())); + let mut arg = Box::pin(EntryArg::new(&proc, &mm, app.clone())); let entry = unsafe { boot.get_function(boot.entry().unwrap()) }; let entry = move || unsafe { entry.exec1(arg.as_mut().as_vec().as_ptr()) }; @@ -482,7 +440,7 @@ fn run( let main: OsThread = unsafe { main.start(stack.start(), stack.len(), entry) }?; // Begin Discord Rich Presence before blocking current thread. - if let Err(e) = discord_presence(param) { + if let Err(e) = discord_presence(¶m) { warn!(e, "Failed to setup Discord rich presence"); } @@ -579,27 +537,6 @@ struct Args { #[arg(long)] #[serde(default)] pro: bool, - - #[arg(long, short)] - execution_engine: Option, -} - -#[derive(Clone, ValueEnum, Deserialize)] -enum ExecutionEngine { - Native, - Llvm, -} - -impl Default for ExecutionEngine { - #[cfg(target_arch = "x86_64")] - fn default() -> Self { - ExecutionEngine::Native - } - - #[cfg(not(target_arch = "x86_64"))] - fn default() -> Self { - ExecutionEngine::Llvm - } } #[derive(Debug, Error)] @@ -643,10 +580,6 @@ enum KernelError { #[error("memory manager initialization failed")] MemoryManagerInitFailed(#[from] MemoryManagerError), - #[cfg(not(target_arch = "x86_64"))] - #[error("the native execution engine is only supported on x86_64")] - NativeExecutionEngineNotSupported, - #[error("tty initialization failed")] TtyInitFailed(#[from] TtyInitError), diff --git a/src/kernel/src/rtld/mod.rs b/src/kernel/src/rtld/mod.rs index 51944c460..cf2f5ff5f 100644 --- a/src/kernel/src/rtld/mod.rs +++ b/src/kernel/src/rtld/mod.rs @@ -2,7 +2,7 @@ pub use self::mem::*; pub use self::module::*; use self::resolver::{ResolveFlags, SymbolResolver}; use crate::budget::ProcType; -use crate::ee::{ExecutionEngine, RawFn}; +use crate::ee::native::{NativeEngine, SetupModuleError}; use crate::errno::{Errno, EINVAL, ENOENT, ENOEXEC, ENOMEM, EPERM, ESRCH}; use crate::fs::{Fs, OpenError, VPath, VPathBuf}; use crate::idt::Entry; @@ -33,21 +33,21 @@ mod resolver; /// An implementation of /// https://github.com/freebsd/freebsd-src/blob/release/9.1.0/libexec/rtld-elf/rtld.c. #[derive(Debug)] -pub struct RuntimeLinker { +pub struct RuntimeLinker { fs: Arc, mm: Arc, - ee: Arc, + ee: Arc, // TODO: Move all fields after this to proc. - list: Gutex>>>, // obj_list + obj_tail - app: Arc>, // obj_main - kernel: Gutex>>>, // obj_kernel - mains: Gutex>>>, // list_main - globals: Gutex>>>, // list_global + list: Gutex>>, // obj_list + obj_tail + app: Arc, // obj_main + kernel: Gutex>>, // obj_kernel + mains: Gutex>>, // list_main + globals: Gutex>>, // list_global tls: Gutex, flags: LinkerFlags, } -impl RuntimeLinker { +impl RuntimeLinker { const NID_CHARS: &'static [u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"; const NID_SALT: [u8; 16] = [ @@ -58,10 +58,10 @@ impl RuntimeLinker { pub fn new( fs: &Arc, mm: &Arc, - ee: &Arc, + ee: &Arc, sys: &mut Syscalls, dump: Option<&Path>, - ) -> Result, RuntimeLinkerError> { + ) -> Result, RuntimeLinkerError> { // Get eboot.bin. let path = vpath!("/app0/eboot.bin"); let file = match fs.open(path, None) { @@ -159,15 +159,15 @@ impl RuntimeLinker { Ok(ld) } - pub fn app(&self) -> &Arc> { + pub fn app(&self) -> &Arc { &self.app } - pub fn kernel(&self) -> Option>> { + pub fn kernel(&self) -> Option> { self.kernel.read().clone() } - pub fn set_kernel(&self, md: Arc>) { + pub fn set_kernel(&self, md: Arc) { *self.kernel.write() = Some(md); } @@ -180,7 +180,7 @@ impl RuntimeLinker { _: LoadFlags, force: bool, main: bool, - ) -> Result>, LoadError> { + ) -> Result, LoadError> { // Check if already loaded. let name = path.file_name().unwrap().to_owned(); let mut list = self.list.write(); @@ -276,7 +276,7 @@ impl RuntimeLinker { })?; // Add to list. - let module = entry.data().clone().downcast::>().unwrap(); + let module = entry.data().clone().downcast::().unwrap(); list.push(module.clone()); @@ -288,7 +288,7 @@ impl RuntimeLinker { } /// See `init_dag` on the PS4 for a reference. - fn init_dag(&self, md: &Arc>) { + fn init_dag(&self, md: &Arc) { // Do nothing if already initializes. let mut flags = md.flags_mut(); @@ -307,7 +307,7 @@ impl RuntimeLinker { /// See `do_dlsym` on the PS4 for a reference. fn resolve_symbol<'a>( &self, - md: &'a Arc>, + md: &'a Arc, mut name: Cow<'a, str>, mut lib: Option<&'a str>, flags: ResolveFlags, @@ -345,7 +345,7 @@ impl RuntimeLinker { None, mname, lib, - SymbolResolver::::hash(Some(name.as_ref()), lib, mname), + SymbolResolver::hash(Some(name.as_ref()), lib, mname), flags | ResolveFlags::UNK3 | ResolveFlags::UNK4, &dags, ) @@ -673,9 +673,9 @@ impl RuntimeLinker { /// No other threads may access the memory of all loaded modules. unsafe fn relocate( &self, - md: &Arc>, - list: &[Arc>], - resolver: &SymbolResolver, + md: &Arc, + list: &[Arc], + resolver: &SymbolResolver, ) -> Result<(), RelocateError> { // TODO: Implement flags & 0x800. self.relocate_single(md, resolver)?; @@ -698,8 +698,8 @@ impl RuntimeLinker { /// No other thread may access the module memory. unsafe fn relocate_single<'b>( &self, - md: &'b Arc>, - resolver: &SymbolResolver<'b, E>, + md: &'b Arc, + resolver: &SymbolResolver<'b>, ) -> Result<(), RelocateError> { // Unprotect the memory. let mut mem = match md.memory().unprotect() { @@ -722,10 +722,10 @@ impl RuntimeLinker { /// See `reloc_non_plt` on the PS4 kernel for a reference. fn relocate_rela<'b>( &self, - md: &'b Arc>, + md: &'b Arc, mem: &mut [u8], - relocated: &mut [Option>], - resolver: &SymbolResolver<'b, E>, + relocated: &mut [Option], + resolver: &SymbolResolver<'b>, ) -> Result<(), RelocateError> { let info = md.file_info().unwrap(); // Let it panic because the PS4 assume it is available. let addr = mem.as_ptr() as usize; @@ -827,10 +827,10 @@ impl RuntimeLinker { /// See `reloc_jmplots` on the PS4 for a reference. fn relocate_plt<'b>( &self, - md: &'b Arc>, + md: &'b Arc, mem: &mut [u8], - relocated: &mut [Option>], - resolver: &SymbolResolver<'b, E>, + relocated: &mut [Option], + resolver: &SymbolResolver<'b>, ) -> Result<(), RelocateError> { // Do nothing if not a dynamic module. let info = match md.file_info() { @@ -878,7 +878,7 @@ impl RuntimeLinker { Ok(()) } - fn get_relocated(md: Arc>, sym: usize) -> (Relocated, usize) { + fn get_relocated(md: Arc, sym: usize) -> (Relocated, usize) { let sym = md.symbol(sym).unwrap(); match sym.ty() { @@ -1110,7 +1110,7 @@ bitflags! { /// Represents the error for [`RuntimeLinker`] initialization. #[derive(Debug, Error)] -pub enum RuntimeLinkerError { +pub enum RuntimeLinkerError { #[error("cannot open {0}")] OpenExeFailed(VPathBuf, #[source] OpenError), @@ -1124,7 +1124,7 @@ pub enum RuntimeLinkerError { MapExeFailed(VPathBuf, #[source] MapError), #[error("cannot setup {0}")] - SetupExeFailed(VPathBuf, #[source] E::SetupModuleErr), + SetupExeFailed(VPathBuf, #[source] SetupModuleError), } /// Represents an error for (S)ELF mapping. @@ -1178,7 +1178,7 @@ pub enum MapError { /// Represents an error for (S)ELF loading. #[derive(Debug, Error)] -pub enum LoadError { +pub enum LoadError { #[error("cannot open the specified file")] OpenFileFailed(#[source] OpenError), @@ -1195,10 +1195,10 @@ pub enum LoadError { ImpureText, #[error("cannot setup the module")] - SetupFailed(#[source] E::SetupModuleErr), + SetupFailed(#[source] SetupModuleError), } -impl Errno for LoadError { +impl Errno for LoadError { fn errno(&self) -> NonZeroI32 { match self { Self::OpenFileFailed(_) => ENOENT, diff --git a/src/kernel/src/rtld/module.rs b/src/kernel/src/rtld/module.rs index 82bf99260..9c9949f48 100644 --- a/src/kernel/src/rtld/module.rs +++ b/src/kernel/src/rtld/module.rs @@ -1,5 +1,5 @@ use super::{MapError, Memory}; -use crate::ee::ExecutionEngine; +use crate::ee::native::{NativeEngine, RawFn}; use crate::fs::{VFile, VPath, VPathBuf}; use crate::log::{print, LogEntry}; use crate::memory::MemoryManager; @@ -19,8 +19,8 @@ use std::sync::Arc; /// An implementation of /// https://github.com/freebsd/freebsd-src/blob/release/9.1.0/libexec/rtld-elf/rtld.h#L147. #[derive(Debug)] -pub struct Module { - ee: Arc, +pub struct Module { + ee: Arc, id: u32, init: Option, entry: Option, @@ -40,7 +40,7 @@ pub struct Module { modules: Vec, libraries: Vec, memory: Memory, - relocated: Gutex>>>, + relocated: Gutex>>, file_info: Option, path: VPathBuf, is_self: bool, @@ -49,10 +49,10 @@ pub struct Module { symbols: Vec, } -impl Module { +impl Module { pub(super) fn map>( mm: &Arc, - ee: &Arc, + ee: &Arc, mut image: Elf, base: usize, mem_name: N, @@ -286,7 +286,7 @@ impl Module { &self.memory } - pub fn relocated_mut(&self) -> GutexWriteGuard<'_, Vec>>> { + pub fn relocated_mut(&self) -> GutexWriteGuard<'_, Vec>> { self.relocated.write() } @@ -314,7 +314,7 @@ impl Module { /// # Safety /// `off` must be a valid offset without base adjustment of a function in the memory of this /// module. - pub unsafe fn get_function(self: &Arc, off: usize) -> Arc { + pub unsafe fn get_function(self: &Arc, off: usize) -> Arc { self.ee .get_function(self, self.memory.addr() + self.memory.base() + off) .unwrap() @@ -758,8 +758,8 @@ pub struct NeededModule { /// Indicated a type of value in the relocation entry. #[derive(Debug)] -pub enum Relocated { - Executable(Arc), - Data((Arc>, usize)), - Tls((Arc>, usize)), +pub enum Relocated { + Executable(Arc), + Data((Arc, usize)), + Tls((Arc, usize)), } diff --git a/src/kernel/src/rtld/resolver.rs b/src/kernel/src/rtld/resolver.rs index b83b4af9f..848d2ac93 100644 --- a/src/kernel/src/rtld/resolver.rs +++ b/src/kernel/src/rtld/resolver.rs @@ -1,23 +1,18 @@ use super::Module; -use crate::ee::ExecutionEngine; use bitflags::bitflags; use elf::Symbol; use std::borrow::Cow; use std::sync::Arc; /// An object to resolve a symbol from loaded (S)ELF. -pub struct SymbolResolver<'a, E: ExecutionEngine> { - mains: &'a [Arc>], - globals: &'a [Arc>], +pub struct SymbolResolver<'a> { + mains: &'a [Arc], + globals: &'a [Arc], new_algorithm: bool, } -impl<'a, E: ExecutionEngine> SymbolResolver<'a, E> { - pub fn new( - mains: &'a [Arc>], - globals: &'a [Arc>], - new_algorithm: bool, - ) -> Self { +impl<'a> SymbolResolver<'a> { + pub fn new(mains: &'a [Arc], globals: &'a [Arc], new_algorithm: bool) -> Self { Self { mains, globals, @@ -28,10 +23,10 @@ impl<'a, E: ExecutionEngine> SymbolResolver<'a, E> { /// See `find_symdef` on the PS4 for a reference. pub fn resolve_with_local( &self, - md: &Arc>, + md: &Arc, index: usize, mut flags: ResolveFlags, - ) -> Option<(Arc>, usize)> { + ) -> Option<(Arc, usize)> { // Check if symbol index is valid. let sym = md.symbols().get(index)?; let data = md.file_info().unwrap(); @@ -102,14 +97,14 @@ impl<'a, E: ExecutionEngine> SymbolResolver<'a, E> { /// See `symlook_default` on the PS4 for a reference. pub fn resolve( &self, - refmod: &'a Arc>, + refmod: &'a Arc, name: Option<&str>, decoded_name: Option<&Cow>, symmod: Option<&str>, symlib: Option<&str>, hash: u64, flags: ResolveFlags, - ) -> Option<(Arc>, usize)> { + ) -> Option<(Arc, usize)> { // TODO: Resolve from DAGs. self.resolve_from_global(refmod, name, decoded_name, symmod, symlib, hash, flags) } @@ -117,14 +112,14 @@ impl<'a, E: ExecutionEngine> SymbolResolver<'a, E> { /// See `symlook_global` on the PS4 for a reference. pub fn resolve_from_global( &self, - refmod: &'a Arc>, + refmod: &'a Arc, name: Option<&str>, decoded_name: Option<&Cow>, symmod: Option<&str>, symlib: Option<&str>, hash: u64, flags: ResolveFlags, - ) -> Option<(Arc>, usize)> { + ) -> Option<(Arc, usize)> { // Resolve from list_main. let mut result = None; @@ -171,15 +166,15 @@ impl<'a, E: ExecutionEngine> SymbolResolver<'a, E> { /// See `symlook_list` on the PS4 for a reference. pub fn resolve_from_list( &self, - refmod: &'a Arc>, + refmod: &'a Arc, name: Option<&str>, decoded_name: Option<&Cow>, symmod: Option<&str>, symlib: Option<&str>, hash: u64, flags: ResolveFlags, - list: &'a [Arc>], - ) -> Option<(Arc>, usize)> { + list: &'a [Arc], + ) -> Option<(Arc, usize)> { // Get module name. let symmod = if !flags.contains(ResolveFlags::UNK2) { symmod @@ -242,15 +237,15 @@ impl<'a, E: ExecutionEngine> SymbolResolver<'a, E> { /// See `symlook_obj` on the PS4 for a reference. pub fn resolve_from_module( &self, - _: &'a Arc>, + _: &'a Arc, name: Option<&str>, decoded_name: Option<&str>, symmod: Option<&str>, symlib: Option<&str>, hash: u64, flags: ResolveFlags, - md: &Arc>, - ) -> Option<(Arc>, usize)> { + md: &Arc, + ) -> Option<(Arc, usize)> { let info = md.file_info().unwrap(); let buckets = info.buckets(); let hash: usize = hash.try_into().unwrap(); @@ -414,7 +409,7 @@ impl<'a, E: ExecutionEngine> SymbolResolver<'a, E> { symlib: Option<&str>, sym: &Symbol, flags: ResolveFlags, - md: &'a Arc>, + md: &'a Arc, ) -> bool { // Check type. let ty = sym.ty(); @@ -499,7 +494,7 @@ impl<'a, E: ExecutionEngine> SymbolResolver<'a, E> { } /// See `convert_mangled_name_to_long` on the PS4 for a reference. - fn decode_legacy(md: &Module, name: &str) -> Option { + fn decode_legacy(md: &Module, name: &str) -> Option { // Split the name. let mut p = name.splitn(3, '#'); let n = p.next()?;