Skip to content

Commit

Permalink
Revises dynamic data parser (#272)
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon authored Jul 25, 2023
1 parent 2e6dc6e commit f8c7631
Show file tree
Hide file tree
Showing 15 changed files with 590 additions and 1,146 deletions.
973 changes: 190 additions & 783 deletions src/elf/src/dynamic.rs

Large diffs are not rendered by default.

387 changes: 190 additions & 197 deletions src/elf/src/info.rs

Large diffs are not rendered by default.

37 changes: 8 additions & 29 deletions src/elf/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
pub use dynamic::*;
pub use info::*;
pub use library::*;
pub use module::*;
pub use program::*;
pub use reloc::*;
pub use ty::*;
Expand All @@ -12,6 +14,8 @@ use thiserror::Error;

mod dynamic;
mod info;
mod library;
mod module;
mod program;
mod reloc;
mod ty;
Expand All @@ -37,7 +41,6 @@ pub struct Elf<I: Read + Seek> {
dynamic: Option<usize>,
dyndata: Option<usize>,
tls: Option<usize>,
dynamic_linking: Option<DynamicLinking>,
proc_param: Option<usize>,
mod_param: Option<usize>,
comment: Option<usize>,
Expand Down Expand Up @@ -174,7 +177,6 @@ impl<I: Read + Seek> Elf<I> {
dynamic: None,
dyndata: None,
tls: None,
dynamic_linking: None,
proc_param: None,
mod_param: None,
comment: None,
Expand Down Expand Up @@ -227,13 +229,6 @@ impl<I: Read + Seek> Elf<I> {
let mut dynoff: usize = dynamic.offset().try_into().unwrap();
let dynsize: usize = dynamic.file_size().try_into().unwrap();

// Read PT_DYNAMIC.
let mut dynamic = vec![0u8; dynamic.file_size() as usize];

if let Err(e) = elf.read_program(i, &mut dynamic) {
return Err(OpenError::ReadDynamicFailed(e));
}

// Check dynamic data.
let i = elf.dyndata.ok_or(OpenError::NoDynData)?;
let dyndata = &elf.programs[i];
Expand All @@ -244,18 +239,18 @@ impl<I: Read + Seek> Elf<I> {

// Adjust dynamic offset inside the dynamic data. It looks weird but this is how Sony
// actually did.
dynoff -= dyndata.offset() as usize;
dynoff -= TryInto::<usize>::try_into(dyndata.offset()).unwrap();

// Read PT_SCE_DYNLIBDATA.
let mut dyndata = vec![0u8; dyndata.file_size() as usize];
let mut dyndata = vec![0u8; dyndata.file_size().try_into().unwrap()];

if let Err(e) = elf.read_program(i, &mut dyndata) {
return Err(OpenError::ReadDynDataFailed(e));
}

// Read PT_SCE_COMMENT.
let comment = if let Some(i) = elf.comment {
let mut buf = vec![0u8; elf.programs[i].file_size() as usize];
let mut buf = vec![0u8; elf.programs[i].file_size().try_into().unwrap()];

if elf.read_program(i, &mut buf).is_err() {
// This is not an error on the PS4.
Expand All @@ -268,16 +263,10 @@ impl<I: Read + Seek> Elf<I> {
};

// Load info.
elf.info = match FileInfo::parse(dyndata.clone(), comment, dynoff, dynsize) {
elf.info = match FileInfo::parse(dyndata, comment, dynoff, dynsize) {
Ok(v) => Some(v),
Err(e) => return Err(OpenError::ParseFileInfoFailed(e)),
};

// Parse PT_DYNAMIC & PT_SCE_DYNLIBDATA.
elf.dynamic_linking = match DynamicLinking::parse(dynamic, dyndata) {
Ok(v) => Some(v),
Err(e) => return Err(OpenError::ParseDynamicLinkingFailed(e)),
};
}

// Check PT_SCE_RELRO.
Expand Down Expand Up @@ -344,10 +333,6 @@ impl<I: Read + Seek> Elf<I> {
self.tls
}

pub fn dynamic_linking(&self) -> Option<&DynamicLinking> {
self.dynamic_linking.as_ref()
}

pub fn proc_param(&self) -> Option<usize> {
self.proc_param
}
Expand Down Expand Up @@ -735,9 +720,6 @@ pub enum OpenError {
#[error("PT_DYNAMIC is not valid")]
InvalidDynamic,

#[error("cannot read PT_DYNAMIC")]
ReadDynamicFailed(#[source] ReadProgramError),

#[error("no PT_SCE_DYNLIBDATA")]
NoDynData,

Expand All @@ -750,9 +732,6 @@ pub enum OpenError {
#[error("cannot parse file info")]
ParseFileInfoFailed(#[source] FileInfoError),

#[error("cannot parse PT_DYNAMIC and PT_SCE_DYNLIBDATA")]
ParseDynamicLinkingFailed(#[source] self::dynamic::ParseError),

#[error("PT_SCE_RELRO has invalid address")]
InvalidRelroAddr,

Expand Down
38 changes: 38 additions & 0 deletions src/elf/src/library.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use bitflags::bitflags;

/// Contains information about the library.
pub struct LibraryInfo {
id: u16,
name: String,
flags: LibraryFlags,
}

impl LibraryInfo {
pub(crate) fn new(id: u16, name: String, flags: LibraryFlags) -> Self {
Self { id, name, flags }
}

pub fn id(&self) -> u16 {
self.id
}

pub fn name(&self) -> &str {
self.name.as_ref()
}

pub fn flags(&self) -> LibraryFlags {
self.flags
}

pub fn flags_mut(&mut self) -> &mut LibraryFlags {
&mut self.flags
}
}

bitflags! {
/// Flags of [`LibraryInfo`].
#[derive(Clone, Copy)]
pub struct LibraryFlags: u64 {
const EXPORT = 0x010000;
}
}
19 changes: 19 additions & 0 deletions src/elf/src/module.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/// Contains information about the module.
pub struct ModuleInfo {
id: u16,
name: String,
}

impl ModuleInfo {
pub(crate) fn new(id: u16, name: String) -> Self {
Self { id, name }
}

pub fn id(&self) -> u16 {
self.id
}

pub fn name(&self) -> &str {
self.name.as_ref()
}
}
7 changes: 0 additions & 7 deletions src/fs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,6 @@ impl From<u16> for FileMode {
}
}

/// Contains some information for SPRX file.
#[derive(Serialize, Deserialize)]
pub struct ModuleInfo {
pub name: String,
pub path: String,
}

/// Errors for [`create_for()`][Metadata::create_for()].
#[derive(Debug, Error)]
pub enum CreateForError {
Expand Down
2 changes: 1 addition & 1 deletion src/kernel/src/ee/native/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ impl<'a, 'b> ExecutionEngine for NativeEngine<'a, 'b> {
let ld = self.rtld.read().unwrap();
let eboot = ld.app();

if eboot.image().dynamic_linking().is_none() {
if eboot.image().dynamic().is_none() {
todo!("A statically linked eboot.bin is not supported yet.");
}

Expand Down
13 changes: 4 additions & 9 deletions src/kernel/src/log/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,19 +97,14 @@ impl LogEntry {
None => return,
};

// Write file name.
// Do nothing if no file name to write.
let file = match file {
Some(v) => {
// Strip 'kernel/src/'.
if v.starts_with("kernel/src/") || v.starts_with("kernel\\src\\") {
&v[11..]
} else {
v
}
}
Some(v) => v,
None => return,
};

// Do not strip "kernel/src/" due to we also set a panic hook. That mean the file path may
// be from another crate.
write!(stdout, ":{file}").unwrap();
write!(self.plain, ":{file}").unwrap();

Expand Down
17 changes: 3 additions & 14 deletions src/kernel/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,16 +319,6 @@ fn print_module(log: &mut LogEntry, module: &Module) {

writeln!(log, "Image type : {}", image.ty()).unwrap();

if let Some(dynamic) = image.dynamic_linking() {
let i = dynamic.module_info();

writeln!(log, "Module name : {}", i.name()).unwrap();

if let Some(f) = dynamic.flags() {
writeln!(log, "Module flags : {f}").unwrap();
}
}

for (i, p) in image.programs().iter().enumerate() {
let offset = p.offset();
let end = offset + p.file_size();
Expand All @@ -344,13 +334,12 @@ fn print_module(log: &mut LogEntry, module: &Module) {
.unwrap();
}

if let Some(dynamic) = image.dynamic_linking() {
for n in dynamic.needed() {
writeln!(log, "Needed : {n}").unwrap();
}
for n in module.needed() {
writeln!(log, "Needed : {}", n.name()).unwrap();
}

// Runtime info.
writeln!(log, "Module flags : {}", module.flags()).unwrap();
writeln!(log, "TLS index : {}", module.tls_index()).unwrap();

// Memory.
Expand Down
8 changes: 4 additions & 4 deletions src/kernel/src/process/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ impl VProc {

// TODO: Invoke signotify at the end.
}
v => return Err(SigmaskError::InvalidArgument(v)),
v => return Err(SigmaskError::InvalidHow(v)),
}

// TODO: Check if we need to invoke reschedule_signals.
Expand All @@ -94,14 +94,14 @@ impl VProc {
/// Represents an error when [`VProc::sigmask()`] is failed.
#[derive(Debug, Error)]
pub enum SigmaskError {
#[error("Invalid argument in sigmask: {0}")]
InvalidArgument(i32),
#[error("{0} is not a valid how")]
InvalidHow(i32),
}

impl Errno for SigmaskError {
fn errno(&self) -> NonZeroI32 {
match self {
Self::InvalidArgument(_) => EINVAL,
Self::InvalidHow(_) => EINVAL,
}
}
}
20 changes: 16 additions & 4 deletions src/kernel/src/rtld/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::errno::{Errno, ENOEXEC};
use crate::fs::path::{VPath, VPathBuf};
use crate::fs::Fs;
use crate::memory::{MemoryManager, MmapError, MprotectError};
use elf::{Elf, FileInfo, FileType, ReadProgramError, Relocation};
use elf::{DynamicFlags, Elf, FileInfo, FileType, ReadProgramError, Relocation};
use std::fs::File;
use std::num::NonZeroI32;
use thiserror::Error;
Expand Down Expand Up @@ -49,11 +49,11 @@ impl<'a> RuntimeLinker<'a> {
// Check image type.
match elf.ty() {
FileType::ET_EXEC | FileType::ET_SCE_EXEC | FileType::ET_SCE_REPLAY_EXEC => {
if elf.dynamic_linking().is_none() {
todo!("A statically linked eboot.bin is not supported yet.");
if elf.info().is_none() {
todo!("a statically linked eboot.bin is not supported yet.");
}
}
FileType::ET_SCE_DYNEXEC if elf.dynamic_linking().is_some() => {}
FileType::ET_SCE_DYNEXEC if elf.dynamic().is_some() => {}
_ => return Err(RuntimeLinkerError::InvalidExe(file.into_vpath())),
}

Expand Down Expand Up @@ -264,6 +264,18 @@ pub enum MapError {

#[error("cannot protect the memory")]
ProtectMemoryFailed(#[source] MprotectError),

#[error("cannot read DT_NEEDED from dynamic entry {0}")]
ReadNeededFailed(usize, #[source] elf::StringTableError),

#[error("{0} is obsolete")]
ObsoleteFlags(DynamicFlags),

#[error("cannot read module info from dynamic entry {0}")]
ReadModuleInfoFailed(usize, #[source] elf::ReadModuleError),

#[error("cannot read libraru info from dynamic entry {0}")]
ReadLibraryInfoFailed(usize, #[source] elf::ReadLibraryError),
}

/// Represents an error for (S)ELF loading.
Expand Down
Loading

0 comments on commit f8c7631

Please sign in to comment.