mirror of
https://github.com/obhq/obliteration.git
synced 2024-05-16 03:40:30 -04:00
Removes LLVM (#743)
This commit is contained in:
parent
469686edc1
commit
ca98770a76
|
@ -1,2 +0,0 @@
|
|||
[env]
|
||||
LLVM_SYS_170_PREFIX = { value = "lib/llvm", relative = true }
|
3
.github/workflows/ci-linux.yml
vendored
3
.github/workflows/ci-linux.yml
vendored
|
@ -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
|
||||
|
|
49
.github/workflows/ci-mac.yml
vendored
49
.github/workflows/ci-mac.yml
vendored
|
@ -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
|
||||
|
|
55
.github/workflows/ci-windows.yml
vendored
55
.github/workflows/ci-windows.yml
vendored
|
@ -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
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,6 +2,5 @@
|
|||
/.flatpak-builder/
|
||||
/.kernel-debug
|
||||
/build/
|
||||
/lib/
|
||||
/src/target/
|
||||
Cargo.lock
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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: .
|
||||
|
|
|
@ -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=<INSTALL_DIR> -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 $<IF:$<CONFIG:Debug>,${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 $<IF:$<CONFIG:Debug>,--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
|
||||
|
|
|
@ -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"] }
|
||||
|
|
|
@ -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 {}
|
|
@ -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<Llvm>,
|
||||
}
|
||||
|
||||
impl LlvmEngine {
|
||||
pub fn new(llvm: &Arc<Llvm>) -> Arc<Self> {
|
||||
Arc::new(Self { llvm: llvm.clone() })
|
||||
}
|
||||
|
||||
fn lift(
|
||||
&self,
|
||||
module: &Module<Self>,
|
||||
) -> Result<crate::llvm::module::ExecutionEngine, LiftError> {
|
||||
// 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<Self>, md: &mut Module<Self>) -> Result<(), Self::SetupModuleErr> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn get_function(
|
||||
self: &Arc<Self>,
|
||||
md: &Arc<Module<Self>>,
|
||||
addr: usize,
|
||||
) -> Result<Arc<Self::RawFn>, 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<R, A>(&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),
|
||||
}
|
|
@ -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<Self>, md: &mut Module<Self>) -> Result<(), Self::SetupModuleErr>;
|
||||
|
||||
unsafe fn get_function(
|
||||
self: &Arc<Self>,
|
||||
md: &Arc<Module<Self>>,
|
||||
addr: usize,
|
||||
) -> Result<Arc<Self::RawFn>, 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<R, A>(&self, a: A) -> R;
|
||||
}
|
||||
|
||||
/// Encapsulate an argument of the PS4 entry point.
|
||||
pub struct EntryArg<E: ExecutionEngine> {
|
||||
pub struct EntryArg {
|
||||
vp: Arc<VProc>,
|
||||
mm: Arc<MemoryManager>,
|
||||
app: Arc<Module<E>>,
|
||||
app: Arc<Module>,
|
||||
name: CString,
|
||||
path: CString,
|
||||
canary: [u8; 64],
|
||||
|
@ -58,8 +25,8 @@ pub struct EntryArg<E: ExecutionEngine> {
|
|||
_pin: PhantomPinned,
|
||||
}
|
||||
|
||||
impl<E: ExecutionEngine> EntryArg<E> {
|
||||
pub fn new(vp: &Arc<VProc>, mm: &Arc<MemoryManager>, app: Arc<Module<E>>) -> Self {
|
||||
impl EntryArg {
|
||||
pub fn new(vp: &Arc<VProc>, mm: &Arc<MemoryManager>, app: Arc<Module>) -> Self {
|
||||
let path = app.path();
|
||||
let name = CString::new(path.file_name().unwrap()).unwrap();
|
||||
let path = CString::new(path.as_str()).unwrap();
|
||||
|
|
|
@ -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<E>(self: &Arc<Self>, module: &mut Module<E>) -> Result<usize, SetupModuleError>
|
||||
where
|
||||
E: ExecutionEngine,
|
||||
{
|
||||
pub fn set_syscalls(&self, v: Syscalls) {
|
||||
self.syscalls.set(v).unwrap();
|
||||
}
|
||||
|
||||
pub fn setup_module(self: &Arc<Self>, md: &mut Module) -> Result<(), SetupModuleError> {
|
||||
self.patch_mod(md)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub unsafe fn get_function(
|
||||
self: &Arc<Self>,
|
||||
md: &Arc<Module>,
|
||||
addr: usize,
|
||||
) -> Result<Arc<RawFn>, GetFunctionError> {
|
||||
Ok(Arc::new(RawFn {
|
||||
md: md.clone(),
|
||||
addr,
|
||||
}))
|
||||
}
|
||||
|
||||
fn patch_mod(self: &Arc<Self>, module: &mut Module) -> Result<usize, SetupModuleError> {
|
||||
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<Self>, md: &mut Module<Self>) -> Result<(), Self::SetupModuleErr> {
|
||||
self.patch_mod(md)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn get_function(
|
||||
self: &Arc<Self>,
|
||||
md: &Arc<Module<Self>>,
|
||||
addr: usize,
|
||||
) -> Result<Arc<Self::RawFn>, 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<R, A>(&self, a: A) -> R {
|
||||
pub unsafe fn exec1<R, A>(&self, a: A) -> R {
|
||||
let f: unsafe extern "sysv64" fn(A) -> R = transmute(self.addr);
|
||||
f(a)
|
||||
}
|
||||
|
|
|
@ -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<LLVMContextRef>,
|
||||
}
|
||||
|
||||
impl Llvm {
|
||||
pub fn new() -> Arc<Self> {
|
||||
let context = unsafe { LLVMContextCreate() };
|
||||
|
||||
Arc::new(Self {
|
||||
context: Mutex::new(context),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn create_module(self: &Arc<Self>, 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<F, R>(&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 {}
|
|
@ -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<Llvm>,
|
||||
module: LLVMModuleRef,
|
||||
}
|
||||
|
||||
impl LlvmModule {
|
||||
pub(super) fn new(llvm: &Arc<Llvm>, module: LLVMModuleRef) -> Self {
|
||||
Self {
|
||||
llvm: llvm.clone(),
|
||||
module,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_execution_engine(mut self) -> Result<ExecutionEngine, Error> {
|
||||
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<Llvm>,
|
||||
ee: LLVMExecutionEngineRef,
|
||||
}
|
||||
|
||||
impl Drop for ExecutionEngine {
|
||||
fn drop(&mut self) {
|
||||
self.llvm
|
||||
.with_context(|_| unsafe { LLVMDisposeExecutionEngine(self.ee) });
|
||||
}
|
||||
}
|
|
@ -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<E: crate::ee::ExecutionEngine>(
|
||||
dump: Option<PathBuf>,
|
||||
param: &Arc<Param>,
|
||||
auth: AuthInfo,
|
||||
mut syscalls: Syscalls,
|
||||
fs: &Arc<Fs>,
|
||||
mm: &Arc<MemoryManager>,
|
||||
ee: Arc<E>,
|
||||
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<E: crate::ee::ExecutionEngine>(
|
|||
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<E: crate::ee::ExecutionEngine>(
|
|||
// 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<E: crate::ee::ExecutionEngine>(
|
|||
|
||||
// Get entry point.
|
||||
let boot = ld.kernel().unwrap();
|
||||
let mut arg = Box::pin(EntryArg::<E>::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<E: crate::ee::ExecutionEngine>(
|
|||
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<ExecutionEngine>,
|
||||
}
|
||||
|
||||
#[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),
|
||||
|
||||
|
|
|
@ -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<E: ExecutionEngine> {
|
||||
pub struct RuntimeLinker {
|
||||
fs: Arc<Fs>,
|
||||
mm: Arc<MemoryManager>,
|
||||
ee: Arc<E>,
|
||||
ee: Arc<NativeEngine>,
|
||||
// TODO: Move all fields after this to proc.
|
||||
list: Gutex<Vec<Arc<Module<E>>>>, // obj_list + obj_tail
|
||||
app: Arc<Module<E>>, // obj_main
|
||||
kernel: Gutex<Option<Arc<Module<E>>>>, // obj_kernel
|
||||
mains: Gutex<Vec<Arc<Module<E>>>>, // list_main
|
||||
globals: Gutex<Vec<Arc<Module<E>>>>, // list_global
|
||||
list: Gutex<Vec<Arc<Module>>>, // obj_list + obj_tail
|
||||
app: Arc<Module>, // obj_main
|
||||
kernel: Gutex<Option<Arc<Module>>>, // obj_kernel
|
||||
mains: Gutex<Vec<Arc<Module>>>, // list_main
|
||||
globals: Gutex<Vec<Arc<Module>>>, // list_global
|
||||
tls: Gutex<TlsAlloc>,
|
||||
flags: LinkerFlags,
|
||||
}
|
||||
|
||||
impl<E: ExecutionEngine> RuntimeLinker<E> {
|
||||
impl RuntimeLinker {
|
||||
const NID_CHARS: &'static [u8] =
|
||||
b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-";
|
||||
const NID_SALT: [u8; 16] = [
|
||||
|
@ -58,10 +58,10 @@ impl<E: ExecutionEngine> RuntimeLinker<E> {
|
|||
pub fn new(
|
||||
fs: &Arc<Fs>,
|
||||
mm: &Arc<MemoryManager>,
|
||||
ee: &Arc<E>,
|
||||
ee: &Arc<NativeEngine>,
|
||||
sys: &mut Syscalls,
|
||||
dump: Option<&Path>,
|
||||
) -> Result<Arc<Self>, RuntimeLinkerError<E>> {
|
||||
) -> Result<Arc<Self>, RuntimeLinkerError> {
|
||||
// Get eboot.bin.
|
||||
let path = vpath!("/app0/eboot.bin");
|
||||
let file = match fs.open(path, None) {
|
||||
|
@ -159,15 +159,15 @@ impl<E: ExecutionEngine> RuntimeLinker<E> {
|
|||
Ok(ld)
|
||||
}
|
||||
|
||||
pub fn app(&self) -> &Arc<Module<E>> {
|
||||
pub fn app(&self) -> &Arc<Module> {
|
||||
&self.app
|
||||
}
|
||||
|
||||
pub fn kernel(&self) -> Option<Arc<Module<E>>> {
|
||||
pub fn kernel(&self) -> Option<Arc<Module>> {
|
||||
self.kernel.read().clone()
|
||||
}
|
||||
|
||||
pub fn set_kernel(&self, md: Arc<Module<E>>) {
|
||||
pub fn set_kernel(&self, md: Arc<Module>) {
|
||||
*self.kernel.write() = Some(md);
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ impl<E: ExecutionEngine> RuntimeLinker<E> {
|
|||
_: LoadFlags,
|
||||
force: bool,
|
||||
main: bool,
|
||||
) -> Result<Arc<Module<E>>, LoadError<E>> {
|
||||
) -> Result<Arc<Module>, LoadError> {
|
||||
// Check if already loaded.
|
||||
let name = path.file_name().unwrap().to_owned();
|
||||
let mut list = self.list.write();
|
||||
|
@ -276,7 +276,7 @@ impl<E: ExecutionEngine> RuntimeLinker<E> {
|
|||
})?;
|
||||
|
||||
// Add to list.
|
||||
let module = entry.data().clone().downcast::<Module<E>>().unwrap();
|
||||
let module = entry.data().clone().downcast::<Module>().unwrap();
|
||||
|
||||
list.push(module.clone());
|
||||
|
||||
|
@ -288,7 +288,7 @@ impl<E: ExecutionEngine> RuntimeLinker<E> {
|
|||
}
|
||||
|
||||
/// See `init_dag` on the PS4 for a reference.
|
||||
fn init_dag(&self, md: &Arc<Module<E>>) {
|
||||
fn init_dag(&self, md: &Arc<Module>) {
|
||||
// Do nothing if already initializes.
|
||||
let mut flags = md.flags_mut();
|
||||
|
||||
|
@ -307,7 +307,7 @@ impl<E: ExecutionEngine> RuntimeLinker<E> {
|
|||
/// See `do_dlsym` on the PS4 for a reference.
|
||||
fn resolve_symbol<'a>(
|
||||
&self,
|
||||
md: &'a Arc<Module<E>>,
|
||||
md: &'a Arc<Module>,
|
||||
mut name: Cow<'a, str>,
|
||||
mut lib: Option<&'a str>,
|
||||
flags: ResolveFlags,
|
||||
|
@ -345,7 +345,7 @@ impl<E: ExecutionEngine> RuntimeLinker<E> {
|
|||
None,
|
||||
mname,
|
||||
lib,
|
||||
SymbolResolver::<E>::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<E: ExecutionEngine> RuntimeLinker<E> {
|
|||
/// No other threads may access the memory of all loaded modules.
|
||||
unsafe fn relocate(
|
||||
&self,
|
||||
md: &Arc<Module<E>>,
|
||||
list: &[Arc<Module<E>>],
|
||||
resolver: &SymbolResolver<E>,
|
||||
md: &Arc<Module>,
|
||||
list: &[Arc<Module>],
|
||||
resolver: &SymbolResolver,
|
||||
) -> Result<(), RelocateError> {
|
||||
// TODO: Implement flags & 0x800.
|
||||
self.relocate_single(md, resolver)?;
|
||||
|
@ -698,8 +698,8 @@ impl<E: ExecutionEngine> RuntimeLinker<E> {
|
|||
/// No other thread may access the module memory.
|
||||
unsafe fn relocate_single<'b>(
|
||||
&self,
|
||||
md: &'b Arc<Module<E>>,
|
||||
resolver: &SymbolResolver<'b, E>,
|
||||
md: &'b Arc<Module>,
|
||||
resolver: &SymbolResolver<'b>,
|
||||
) -> Result<(), RelocateError> {
|
||||
// Unprotect the memory.
|
||||
let mut mem = match md.memory().unprotect() {
|
||||
|
@ -722,10 +722,10 @@ impl<E: ExecutionEngine> RuntimeLinker<E> {
|
|||
/// See `reloc_non_plt` on the PS4 kernel for a reference.
|
||||
fn relocate_rela<'b>(
|
||||
&self,
|
||||
md: &'b Arc<Module<E>>,
|
||||
md: &'b Arc<Module>,
|
||||
mem: &mut [u8],
|
||||
relocated: &mut [Option<Relocated<E>>],
|
||||
resolver: &SymbolResolver<'b, E>,
|
||||
relocated: &mut [Option<Relocated>],
|
||||
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<E: ExecutionEngine> RuntimeLinker<E> {
|
|||
/// See `reloc_jmplots` on the PS4 for a reference.
|
||||
fn relocate_plt<'b>(
|
||||
&self,
|
||||
md: &'b Arc<Module<E>>,
|
||||
md: &'b Arc<Module>,
|
||||
mem: &mut [u8],
|
||||
relocated: &mut [Option<Relocated<E>>],
|
||||
resolver: &SymbolResolver<'b, E>,
|
||||
relocated: &mut [Option<Relocated>],
|
||||
resolver: &SymbolResolver<'b>,
|
||||
) -> Result<(), RelocateError> {
|
||||
// Do nothing if not a dynamic module.
|
||||
let info = match md.file_info() {
|
||||
|
@ -878,7 +878,7 @@ impl<E: ExecutionEngine> RuntimeLinker<E> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn get_relocated(md: Arc<Module<E>>, sym: usize) -> (Relocated<E>, usize) {
|
||||
fn get_relocated(md: Arc<Module>, 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<E: ExecutionEngine> {
|
||||
pub enum RuntimeLinkerError {
|
||||
#[error("cannot open {0}")]
|
||||
OpenExeFailed(VPathBuf, #[source] OpenError),
|
||||
|
||||
|
@ -1124,7 +1124,7 @@ pub enum RuntimeLinkerError<E: ExecutionEngine> {
|
|||
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<E: ExecutionEngine> {
|
||||
pub enum LoadError {
|
||||
#[error("cannot open the specified file")]
|
||||
OpenFileFailed(#[source] OpenError),
|
||||
|
||||
|
@ -1195,10 +1195,10 @@ pub enum LoadError<E: ExecutionEngine> {
|
|||
ImpureText,
|
||||
|
||||
#[error("cannot setup the module")]
|
||||
SetupFailed(#[source] E::SetupModuleErr),
|
||||
SetupFailed(#[source] SetupModuleError),
|
||||
}
|
||||
|
||||
impl<E: ExecutionEngine> Errno for LoadError<E> {
|
||||
impl Errno for LoadError {
|
||||
fn errno(&self) -> NonZeroI32 {
|
||||
match self {
|
||||
Self::OpenFileFailed(_) => ENOENT,
|
||||
|
|
|
@ -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<E: ExecutionEngine + ?Sized> {
|
||||
ee: Arc<E>,
|
||||
pub struct Module {
|
||||
ee: Arc<NativeEngine>,
|
||||
id: u32,
|
||||
init: Option<usize>,
|
||||
entry: Option<usize>,
|
||||
|
@ -40,7 +40,7 @@ pub struct Module<E: ExecutionEngine + ?Sized> {
|
|||
modules: Vec<ModuleInfo>,
|
||||
libraries: Vec<LibraryInfo>,
|
||||
memory: Memory,
|
||||
relocated: Gutex<Vec<Option<Relocated<E>>>>,
|
||||
relocated: Gutex<Vec<Option<Relocated>>>,
|
||||
file_info: Option<FileInfo>,
|
||||
path: VPathBuf,
|
||||
is_self: bool,
|
||||
|
@ -49,10 +49,10 @@ pub struct Module<E: ExecutionEngine + ?Sized> {
|
|||
symbols: Vec<Symbol>,
|
||||
}
|
||||
|
||||
impl<E: ExecutionEngine> Module<E> {
|
||||
impl Module {
|
||||
pub(super) fn map<N: Into<String>>(
|
||||
mm: &Arc<MemoryManager>,
|
||||
ee: &Arc<E>,
|
||||
ee: &Arc<NativeEngine>,
|
||||
mut image: Elf<VFile>,
|
||||
base: usize,
|
||||
mem_name: N,
|
||||
|
@ -286,7 +286,7 @@ impl<E: ExecutionEngine> Module<E> {
|
|||
&self.memory
|
||||
}
|
||||
|
||||
pub fn relocated_mut(&self) -> GutexWriteGuard<'_, Vec<Option<Relocated<E>>>> {
|
||||
pub fn relocated_mut(&self) -> GutexWriteGuard<'_, Vec<Option<Relocated>>> {
|
||||
self.relocated.write()
|
||||
}
|
||||
|
||||
|
@ -314,7 +314,7 @@ impl<E: ExecutionEngine> Module<E> {
|
|||
/// # 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<Self>, off: usize) -> Arc<E::RawFn> {
|
||||
pub unsafe fn get_function(self: &Arc<Self>, off: usize) -> Arc<RawFn> {
|
||||
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<E: ExecutionEngine + ?Sized> {
|
||||
Executable(Arc<E::RawFn>),
|
||||
Data((Arc<Module<E>>, usize)),
|
||||
Tls((Arc<Module<E>>, usize)),
|
||||
pub enum Relocated {
|
||||
Executable(Arc<RawFn>),
|
||||
Data((Arc<Module>, usize)),
|
||||
Tls((Arc<Module>, usize)),
|
||||
}
|
||||
|
|
|
@ -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<Module<E>>],
|
||||
globals: &'a [Arc<Module<E>>],
|
||||
pub struct SymbolResolver<'a> {
|
||||
mains: &'a [Arc<Module>],
|
||||
globals: &'a [Arc<Module>],
|
||||
new_algorithm: bool,
|
||||
}
|
||||
|
||||
impl<'a, E: ExecutionEngine> SymbolResolver<'a, E> {
|
||||
pub fn new(
|
||||
mains: &'a [Arc<Module<E>>],
|
||||
globals: &'a [Arc<Module<E>>],
|
||||
new_algorithm: bool,
|
||||
) -> Self {
|
||||
impl<'a> SymbolResolver<'a> {
|
||||
pub fn new(mains: &'a [Arc<Module>], globals: &'a [Arc<Module>], 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<Module<E>>,
|
||||
md: &Arc<Module>,
|
||||
index: usize,
|
||||
mut flags: ResolveFlags,
|
||||
) -> Option<(Arc<Module<E>>, usize)> {
|
||||
) -> Option<(Arc<Module>, 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<Module<E>>,
|
||||
refmod: &'a Arc<Module>,
|
||||
name: Option<&str>,
|
||||
decoded_name: Option<&Cow<str>>,
|
||||
symmod: Option<&str>,
|
||||
symlib: Option<&str>,
|
||||
hash: u64,
|
||||
flags: ResolveFlags,
|
||||
) -> Option<(Arc<Module<E>>, usize)> {
|
||||
) -> Option<(Arc<Module>, 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<Module<E>>,
|
||||
refmod: &'a Arc<Module>,
|
||||
name: Option<&str>,
|
||||
decoded_name: Option<&Cow<str>>,
|
||||
symmod: Option<&str>,
|
||||
symlib: Option<&str>,
|
||||
hash: u64,
|
||||
flags: ResolveFlags,
|
||||
) -> Option<(Arc<Module<E>>, usize)> {
|
||||
) -> Option<(Arc<Module>, 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<Module<E>>,
|
||||
refmod: &'a Arc<Module>,
|
||||
name: Option<&str>,
|
||||
decoded_name: Option<&Cow<str>>,
|
||||
symmod: Option<&str>,
|
||||
symlib: Option<&str>,
|
||||
hash: u64,
|
||||
flags: ResolveFlags,
|
||||
list: &'a [Arc<Module<E>>],
|
||||
) -> Option<(Arc<Module<E>>, usize)> {
|
||||
list: &'a [Arc<Module>],
|
||||
) -> Option<(Arc<Module>, 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<Module<E>>,
|
||||
_: &'a Arc<Module>,
|
||||
name: Option<&str>,
|
||||
decoded_name: Option<&str>,
|
||||
symmod: Option<&str>,
|
||||
symlib: Option<&str>,
|
||||
hash: u64,
|
||||
flags: ResolveFlags,
|
||||
md: &Arc<Module<E>>,
|
||||
) -> Option<(Arc<Module<E>>, usize)> {
|
||||
md: &Arc<Module>,
|
||||
) -> Option<(Arc<Module>, 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<Module<E>>,
|
||||
md: &'a Arc<Module>,
|
||||
) -> 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<E>, name: &str) -> Option<String> {
|
||||
fn decode_legacy(md: &Module, name: &str) -> Option<String> {
|
||||
// Split the name.
|
||||
let mut p = name.splitn(3, '#');
|
||||
let n = p.next()?;
|
||||
|
|
Loading…
Reference in a new issue