Implements sys_dynlib_get_info (#672)

This commit is contained in:
SuchAFuriousDeath 2024-04-05 23:05:05 +02:00 committed by GitHub
parent f6023d48e5
commit b741095180
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 303 additions and 103 deletions

View file

@ -279,7 +279,7 @@ impl FileInfo {
let id = LE::read_u16(&data[6..]);
// Lookup name.
let name = match self.read_str(name.try_into().unwrap()) {
let name = match self.read_str(name as usize) {
Ok(v) => v.to_owned(),
Err(e) => return Err(ReadModuleError::InvalidNameOffset(name, e)),
};
@ -301,6 +301,15 @@ impl FileInfo {
Ok(LibraryInfo::new(id, name, LibraryFlags::empty()))
}
pub fn read_fingerprint(&self, offset: usize) -> [u8; 20] {
let offset = offset + self.dynoff;
let mut fingerprint = [0u8; 20];
fingerprint.copy_from_slice(&self.data[offset..(offset + 20)]);
fingerprint
}
pub fn read_str(&self, offset: usize) -> Result<&str, StringTableError> {
// Get raw string.
let tab = &self.data[self.strtab..(self.strtab + self.strsz)];
@ -316,7 +325,9 @@ impl FileInfo {
};
// Get Rust string.
std::str::from_utf8(raw).map_err(|_| StringTableError::NotUtf8)
let string = std::str::from_utf8(raw)?;
Ok(string)
}
}
@ -419,3 +430,9 @@ pub enum StringTableError {
#[error("the offset is not a UTF-8 string")]
NotUtf8,
}
impl From<std::str::Utf8Error> for StringTableError {
fn from(_: std::str::Utf8Error) -> Self {
Self::NotUtf8
}
}

View file

@ -336,6 +336,10 @@ impl<I: Read + Seek> Elf<I> {
self.programs.as_slice()
}
pub fn relro(&self) -> Option<usize> {
self.relro
}
pub fn dynamic(&self) -> Option<usize> {
self.dynamic
}

View file

@ -90,3 +90,13 @@ pub enum ProcType {
MiniApp,
System, // TODO: Verify this.
}
impl Into<u32> for ProcType {
fn into(self) -> u32 {
match self {
ProcType::BigApp => 0,
ProcType::MiniApp => 1,
ProcType::System => 2,
}
}
}

View file

@ -43,18 +43,10 @@ impl TryInto<DmemContainer> for i32 {
}
}
impl TryInto<DmemContainer> for usize {
type Error = SysErr;
fn try_into(self) -> Result<DmemContainer, Self::Error> {
(self as i32).try_into()
}
}
impl DeviceDriver for Dmem {
fn ioctl(
&self,
dev: &Arc<CharacterDevice>,
_: &Arc<CharacterDevice>,
cmd: IoCmd,
td: Option<&VThread>,
) -> Result<(), Box<dyn Errno>> {
@ -76,7 +68,8 @@ impl DeviceDriver for Dmem {
}
match cmd {
IoCmd::DMEM10(size) => *size = self.total_size,
// TODO: properly implement this
IoCmd::DMEMTOTAL(size) => *size = self.total_size,
IoCmd::DMEMGETPRT(_prt) => todo!(),
IoCmd::DMEMGETAVAIL(_avail) => todo!(),
IoCmd::DMEMALLOC(_alloc) => todo!(),

View file

@ -6,6 +6,12 @@ use std::sync::Arc;
#[derive(Debug)]
pub struct BlockPool {}
impl BlockPool {
pub fn new() -> Arc<Self> {
Arc::new(Self {})
}
}
impl FileBackend for BlockPool {
#[allow(unused_variables)] // TODO: remove when implementing
fn ioctl(

View file

@ -1,14 +1,15 @@
use thiserror::Error;
use crate::dev::{Dmem, DmemContainer};
use crate::errno::EINVAL;
use crate::fs::{make_dev, CharacterDevice, DriverFlags, Fs, MakeDevError, MakeDevFlags, Mode};
use crate::fs::{
make_dev, CharacterDevice, DriverFlags, Fs, MakeDevError, MakeDevFlags, Mode, VFile, VFileType,
};
use crate::info;
use crate::process::{VProc, VThread};
use crate::process::VThread;
use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls};
use crate::ucred::{Gid, Privilege, Uid};
use crate::ucred::{Gid, Uid};
use std::ops::Index;
use std::sync::Arc;
use thiserror::Error;
pub use self::blockpool::*;
@ -112,24 +113,31 @@ impl DmemManager {
fn sys_dmem_container(self: &Arc<Self>, td: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
let dmem_id: i32 = i.args[0].try_into().unwrap();
let mut dmem_container = td.proc().dmem_container_mut();
let old_dmem_container = *dmem_container;
let dmem_container = td.proc().dmem_container_mut();
let current_container = *dmem_container;
if dmem_id != -1 {
todo!()
}
Ok(old_dmem_container.into())
Ok(current_container.into())
}
fn sys_blockpool_open(self: &Arc<Self>, _td: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
fn sys_blockpool_open(self: &Arc<Self>, td: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
let flags: u32 = i.args[0].try_into().unwrap();
if flags & 0xffafffff != 0 {
return Err(SysErr::Raw(EINVAL));
}
todo!("sys_blockpool_open on new FS")
let bp = BlockPool::new();
let fd = td
.proc()
.files()
.alloc(Arc::new(VFile::new(VFileType::Blockpool(bp))));
Ok(fd.into())
}
fn sys_blockpool_map(self: &Arc<Self>, _: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
@ -158,10 +166,6 @@ impl DmemManager {
fn sys_blockpool_move(self: &Arc<Self>, _: &VThread, _i: &SysIn) -> Result<SysOut, SysErr> {
todo!()
}
fn get_dmem_device<'a>(self: &'a Arc<Self>, dmem: DmemContainer) -> &'a DmemDevice {
self.index(dmem)
}
}
impl Index<DmemContainer> for DmemManager {

View file

@ -24,7 +24,7 @@ pub struct VFile {
}
impl VFile {
pub(super) fn new(ty: VFileType) -> Self {
pub fn new(ty: VFileType) -> Self {
let gg = GutexGroup::new();
Self {

View file

@ -112,7 +112,7 @@ commands! {
DIPSWCHECK2(&mut i32) = 0x40048806,
/// Get total size?
DMEM10(&mut usize) = 0x4008800a,
DMEMTOTAL(&mut usize) = 0x4008800a,
/// Get PRT aperture
DMEMGETPRT(&mut PrtAperture) = 0xC018800C,
/// Get available memory size

View file

@ -443,7 +443,7 @@ impl Fs {
// Our IoCmd contains both the command and the argument (if there is one).
let cmd = IoCmd::try_from_raw_parts(i.args[1].into(), i.args[2].into())?;
info!("Executing ioctl({cmd:?}) on file descriptor {fd}.");
info!("Executing ioctl {cmd:?} on file descriptor {fd}.");
self.ioctl(fd, cmd, td)?;

View file

@ -434,7 +434,7 @@ fn run() -> Result<(), KernelError> {
.load(path, flags, false, true, &main)
.map_err(|e| KernelError::FailedToLoadLibkernel(e.into()))?;
libkernel.flags_mut().remove(ModuleFlags::UNK2);
libkernel.flags_mut().remove(ModuleFlags::IS_NEW);
libkernel.print(info!());
ld.set_kernel(libkernel);
@ -448,7 +448,7 @@ fn run() -> Result<(), KernelError> {
.load(path, flags, false, true, &main)
.map_err(|e| KernelError::FailedToLoadLibSceLibcInternal(e.into()))?;
libc.flags_mut().remove(ModuleFlags::UNK2);
libc.flags_mut().remove(ModuleFlags::IS_NEW);
libc.print(info!());
drop(libc);

View file

@ -783,7 +783,7 @@ impl VProc {
ProcTypeInfo {
len: size_of::<ProcTypeInfo>(),
ty: self.budget_ptype as u32,
ty: self.budget_ptype.into(),
flags,
}
}

View file

@ -132,7 +132,7 @@ impl RegMgr {
// Lookup the entry.
let key = RegKey::new(key);
let entry = self.lookup(key).ok_or(RegError::NotFound(key))?;
let web = if cred.is_webcore_process() || cred.is_diskplayerui_process() {
let web = if cred.is_libkernel_web() || cred.is_webprocess_webapp_or_webmas() {
1
} else {
0

View file

@ -20,6 +20,7 @@ pub struct Memory {
base: usize,
text: usize,
data: usize,
relro: Option<usize>,
obcode: usize,
obcode_sealed: Gutex<usize>,
obdata: usize,
@ -61,10 +62,8 @@ impl Memory {
}
}
ProgramType::PT_SCE_RELRO => {
if relro.is_some() {
if relro.replace(segments.len()).is_some() {
return Err(MapError::MultipleRelroProgram);
} else {
relro = Some(segments.len());
}
}
_ => continue,
@ -132,7 +131,7 @@ impl Memory {
len += segment.len;
segments.push(segment);
// Create workspace for our data. We cannot mix this the code because the executable-space
// Create workspace for our data. We cannot mix this with the code because the executable-space
// protection on some system don't allow execution on writable page.
let obdata = segments.len();
let segment = MemorySegment {
@ -180,6 +179,7 @@ impl Memory {
base,
text,
data,
relro,
obcode,
obcode_sealed: gg.spawn(0),
obdata,
@ -212,6 +212,10 @@ impl Memory {
&self.segments[self.data]
}
pub fn relro_segment(&self) -> Option<&MemorySegment> {
self.relro.as_ref().map(|i| &self.segments[*i])
}
/// # Safety
/// Some part of the returned slice may not readable.
pub unsafe fn as_bytes(&self) -> &[u8] {

View file

@ -129,7 +129,7 @@ impl RuntimeLinker {
)
.map_err(ExecError::MapFailed)?;
*app.flags_mut() |= ModuleFlags::MAIN_PROG;
*app.flags_mut() |= ModuleFlags::MAINPROG;
self.ee
.setup_module(&mut app)
@ -270,7 +270,7 @@ impl RuntimeLinker {
// TODO: Check the call to sceSblAuthMgrIsLoadable in the self_load_shared_object on the PS4
// to see how it is return the value.
if name != "libc.sprx" && name != "libSceFios2.sprx" {
*md.flags_mut() |= ModuleFlags::UNK1;
*md.flags_mut() |= ModuleFlags::IS_SYSTEM;
}
if let Err(e) = self.ee.setup_module(&mut md) {
@ -335,7 +335,7 @@ impl RuntimeLinker {
// Resolve.
let dags = md.dag_static();
let sym = if md.flags().intersects(ModuleFlags::MAIN_PROG) {
let sym = if md.flags().intersects(ModuleFlags::MAINPROG) {
todo!("do_dlsym on MAIN_PROG");
} else {
resolver.resolve_from_list(
@ -451,8 +451,95 @@ impl RuntimeLinker {
Ok(SysOut::ZERO)
}
fn sys_dynlib_get_info(self: &Arc<Self>, _td: &VThread, _i: &SysIn) -> Result<SysOut, SysErr> {
todo!()
fn sys_dynlib_get_info(self: &Arc<Self>, td: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
let handle: u32 = i.args[0].try_into().unwrap();
let info = {
let info_out: *mut DynlibInfo = i.args[1].into();
unsafe { &mut *info_out }
};
info!("Getting info for module id = {}.", handle);
let bin = td.proc().bin();
let bin = match bin.as_ref() {
Some(bin) if bin.app().file_info().is_some() => bin,
_ => return Err(SysErr::Raw(EPERM)),
};
if info.size != size_of::<DynlibInfo>() {
return Err(SysErr::Raw(EINVAL));
}
*info = self.dynlib_get_info(handle, bin, true)?;
Ok(SysOut::ZERO)
}
fn dynlib_get_info(
&self,
handle: u32,
bin: &Binaries,
no_system: bool,
) -> Result<DynlibInfo, SysErr> {
let mut info: DynlibInfo = unsafe { zeroed() };
let mut modules = bin.list();
let md = modules
.find(|m| m.id() == handle)
.ok_or(SysErr::Raw(ESRCH))?;
if no_system && md.flags().intersects(ModuleFlags::IS_SYSTEM) {
return Err(SysErr::Raw(EPERM));
}
let name = md.path().file_name().unwrap();
let mem = md.memory();
let addr = mem.addr();
info.name[..name.len()].copy_from_slice(name.as_bytes());
info.name[0xff] = 0;
info.segment_count = 2;
info.text_segment.addr = mem.base();
info.text_segment.size = mem.text_segment().len().try_into().unwrap();
info.text_segment.prot = 5;
info.data_segment.addr = addr + mem.data_segment().start();
info.data_segment.size = mem.data_segment().len().try_into().unwrap();
info.data_segment.prot = 3;
if let Some(seg) = mem.relro_segment() {
info.relro_segment.addr = addr + seg.start();
info.relro_segment.size = seg.len().try_into().unwrap();
info.relro_segment.prot = 1;
info.segment_count += 1;
};
info.fingerprint = md.fingerprint();
let mut e = info!();
writeln!(
e,
"Retrieved info for module {} (ID = {}).",
md.path(),
handle
)
.unwrap();
writeln!(e, "mapbase : {:#x}", info.text_segment.addr).unwrap();
writeln!(e, "textsize: {:#x}", info.text_segment.size).unwrap();
writeln!(e, "database: {:#x}", info.data_segment.addr).unwrap();
writeln!(e, "datasize: {:#x}", info.data_segment.size).unwrap();
print(e);
Ok(info)
}
fn sys_dynlib_load_prx(self: &Arc<Self>, td: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
@ -703,7 +790,7 @@ impl RuntimeLinker {
self.relocate_rela(md, mem.as_mut(), &mut relocated, resolver)?;
if !md.flags().contains(ModuleFlags::UNK4) {
if !md.flags().contains(ModuleFlags::JMPSLOTS_DONE) {
self.relocate_plt(md, mem.as_mut(), &mut relocated, resolver)?;
}
@ -892,6 +979,8 @@ impl RuntimeLinker {
let flags: u32 = i.args[1].try_into().unwrap();
let info: *mut DynlibInfoEx = i.args[2].into();
info!("Getting info_ex for module id = {}.", handle);
// Check if application is dynamic linking.
let bin = td.proc().bin();
let bin = bin.as_ref().ok_or(SysErr::Raw(EPERM))?;
@ -901,9 +990,8 @@ impl RuntimeLinker {
}
// Check buffer size.
let size: usize = unsafe { (*info).size.try_into().unwrap() };
if size != size_of::<DynlibInfoEx>() {
if unsafe { (*info).size } != size_of::<DynlibInfoEx>() {
return Err(SysErr::Raw(EINVAL));
}
@ -920,17 +1008,20 @@ impl RuntimeLinker {
*info = unsafe { zeroed() };
info.handle = md.id();
info.mapbase = addr + mem.base();
info.textsize = mem.text_segment().len().try_into().unwrap();
info.unk3 = 5;
info.database = addr + mem.data_segment().start();
info.datasize = mem.data_segment().len().try_into().unwrap();
info.unk4 = 3;
info.unk6 = 2;
info.text_segment.addr = addr + mem.base();
info.text_segment.size = mem.text_segment().len().try_into().unwrap();
info.text_segment.prot = 5;
info.data_segment.addr = addr + mem.data_segment().start();
info.data_segment.size = mem.data_segment().len().try_into().unwrap();
info.data_segment.prot = 3;
info.segment_count = 2;
info.refcount = *md.ref_count();
// Copy module name.
if flags & 2 == 0 || !md.flags().contains(ModuleFlags::UNK1) {
if flags & 2 == 0 || !md.flags().contains(ModuleFlags::IS_SYSTEM) {
let name = md.path().file_name().unwrap();
info.name[..name.len()].copy_from_slice(name.as_bytes());
@ -941,13 +1032,13 @@ impl RuntimeLinker {
// Let's keep the same behavior as the PS4 for now.
info.tlsindex = if flags & 1 != 0 {
let flags = md.flags();
let mut upper = if flags.contains(ModuleFlags::UNK1) {
let mut upper = if flags.contains(ModuleFlags::IS_SYSTEM) {
1
} else {
0
};
if flags.contains(ModuleFlags::MAIN_PROG) {
if flags.contains(ModuleFlags::MAINPROG) {
upper += 2;
}
@ -968,7 +1059,7 @@ impl RuntimeLinker {
info.tlsoffset = (*md.tls_offset()).try_into().unwrap();
// Initialization and finalization functions.
if !md.flags().contains(ModuleFlags::UNK5) {
if !md.flags().contains(ModuleFlags::NOT_GET_PROC) {
info.init = md.init().map(|v| addr + v).unwrap_or(0);
info.fini = md.fini().map(|v| addr + v).unwrap_or(0);
}
@ -987,15 +1078,16 @@ impl RuntimeLinker {
writeln!(
e,
"Retrieved info for module {} (ID = {}).",
"Retrieved info_ex for module {} (ID = {}).",
md.path(),
handle
)
.unwrap();
writeln!(e, "mapbase : {:#x}", info.mapbase).unwrap();
writeln!(e, "textsize : {:#x}", info.textsize).unwrap();
writeln!(e, "database : {:#x}", info.database).unwrap();
writeln!(e, "datasize : {:#x}", info.datasize).unwrap();
writeln!(e, "mapbase : {:#x}", info.text_segment.addr).unwrap();
writeln!(e, "textsize : {:#x}", info.text_segment.size).unwrap();
writeln!(e, "database : {:#x}", info.data_segment.addr).unwrap();
writeln!(e, "datasize : {:#x}", info.data_segment.size).unwrap();
writeln!(e, "tlsindex : {}", info.tlsindex).unwrap();
writeln!(e, "tlsinit : {:#x}", info.tlsinit).unwrap();
writeln!(e, "tlsoffset : {:#x}", info.tlsoffset).unwrap();
@ -1043,9 +1135,33 @@ impl RuntimeLinker {
}
}
#[derive(Debug)]
#[repr(C)]
struct SegmentInfo {
addr: usize,
size: u32,
prot: u32,
}
#[derive(Debug)]
#[repr(C)]
struct DynlibInfo {
size: usize,
name: [u8; 256],
text_segment: SegmentInfo,
data_segment: SegmentInfo,
relro_segment: SegmentInfo,
unk_segment: SegmentInfo,
segment_count: u32,
fingerprint: [u8; 0x14],
}
const _: () = assert!(size_of::<DynlibInfo>() == 0x160);
#[derive(Debug)]
#[repr(C)]
struct DynlibInfoEx {
size: u64,
size: usize,
name: [u8; 256],
handle: u32,
tlsindex: u32,
@ -1062,17 +1178,16 @@ struct DynlibInfoEx {
eh_frame: usize,
eh_frame_hdr_size: u32,
eh_frame_size: u32,
mapbase: usize,
textsize: u32,
unk3: u32, // Always 5.
database: usize,
datasize: u32,
unk4: u32, // Always 3.
unk5: [u8; 0x20], // Always zeroes.
unk6: u32, // Always 2.
text_segment: SegmentInfo,
data_segment: SegmentInfo,
relro_segment: SegmentInfo,
unk_segment: SegmentInfo,
segment_count: u32, // Always 2.
refcount: u32,
}
const _: () = assert!(size_of::<DynlibInfoEx>() == 0x1a8);
/// Contains how TLS was allocated so far.
#[derive(Debug)]
pub struct TlsAlloc {

View file

@ -39,6 +39,7 @@ pub struct Module {
needed: Vec<NeededModule>,
modules: Vec<ModuleInfo>,
libraries: Vec<LibraryInfo>,
fingerprint: [u8; 20],
memory: Memory,
relocated: Gutex<Vec<Option<Relocated>>>,
file_info: Option<FileInfo>,
@ -173,13 +174,14 @@ impl Module {
proc_param,
mod_param,
sdk_ver,
flags: gg.spawn(ModuleFlags::UNK2),
flags: gg.spawn(ModuleFlags::IS_NEW),
names,
dag_static: gg.spawn(Vec::new()),
dag_dynamic: gg.spawn(Vec::new()),
needed: Vec::new(),
modules: Vec::new(),
libraries: Vec::new(),
fingerprint: [0; 20],
memory,
relocated: gg.spawn(Vec::new()),
file_info: None,
@ -284,6 +286,10 @@ impl Module {
self.libraries.as_ref()
}
pub fn fingerprint(&self) -> [u8; 20] {
self.fingerprint
}
pub fn memory(&self) -> &Memory {
&self.memory
}
@ -550,6 +556,8 @@ impl Module {
/// See `digest_dynamic` on the PS4 for a reference.
fn digest_dynamic(&mut self, base: usize, info: &FileInfo) -> Result<(), MapError> {
// TODO: Implement the remaining tags.
let mut fingerprint_offset = None;
for (i, (tag, value)) in info.dynamic().enumerate() {
match tag {
DynamicTag::DT_NULL => break,
@ -579,6 +587,9 @@ impl Module {
DynamicTag::DT_SONAME => self.digest_soname(info, i, value)?,
DynamicTag::DT_TEXTREL => *self.flags.get_mut() |= ModuleFlags::TEXT_REL,
DynamicTag::DT_FLAGS => self.digest_flags(value)?,
DynamicTag::DT_SCE_FINGERPRINT => {
fingerprint_offset = Some(u64::from_le_bytes(value) as usize)
}
DynamicTag::DT_SCE_MODULE_INFO | DynamicTag::DT_SCE_NEEDED_MODULE => {
self.digest_module_info(info, i, value)?;
}
@ -589,6 +600,8 @@ impl Module {
}
}
self.digest_fingerprint(info, fingerprint_offset.unwrap_or(0));
Ok(())
}
@ -645,6 +658,12 @@ impl Module {
Ok(())
}
fn digest_fingerprint(&mut self, info: &FileInfo, offset: usize) {
let fingerprint = info.read_fingerprint(offset);
self.fingerprint = fingerprint;
}
fn digest_module_info(
&mut self,
info: &FileInfo,
@ -739,18 +758,17 @@ bitflags! {
/// Flags for [`Module`].
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ModuleFlags: u16 {
const MAIN_PROG = 0x0001;
const MAINPROG = 0x0001;
const TEXT_REL = 0x0002;
const JMPSLOTS_DONE = 0x0004; // TODO: This seems incorrect.
const TLS_DONE = 0x0008;
const INIT_SCANNED = 0x0010;
const ON_FINI_LIST = 0x0020;
const DAG_INITED = 0x0040;
const UNK1 = 0x0100; // TODO: Rename this.
const UNK2 = 0x0200; // TODO: Rename this.
const UNK3 = 0x0400; // TODO: Rename this.
const UNK4 = 0x0800; // TODO: It seems like this is actually JMPSLOTS_DONE.
const UNK5 = 0x1000; // TODO: Rename this.
const IS_SYSTEM = 0x0100;
const IS_NEW = 0x0200;
const LIBC_FIOS = 0x0400;
const JMPSLOTS_DONE = 0x0800;
const NOT_GET_PROC = 0x1000;
}
}

View file

@ -72,7 +72,7 @@ impl AuthPaid {
/// A wrapper type for `caps` field of [`AuthInfo`].
#[repr(transparent)]
#[derive(Debug, Clone)]
pub struct AuthCaps([u64; 4]);
pub struct AuthCaps(pub(super) [u64; 4]);
impl AuthCaps {
pub fn new(raw: [u64; 4]) -> Self {
@ -87,14 +87,6 @@ impl AuthCaps {
(self.0[0] & 0x2000000000000000) != 0
}
pub fn is_jit_compiler_process(&self) -> bool {
todo!()
}
pub fn is_jit_application_process(&self) -> bool {
todo!()
}
pub fn has_use_video_service_capability(&self) -> bool {
self.0[0] >> 0x39 & 1 != 0
}
@ -126,11 +118,20 @@ impl AuthAttrs {
}
pub fn has_sce_program_attribute(&self) -> bool {
todo!()
(self.0[0] & 0x80000000) != 0
}
pub fn is_debuggable_process(&self) -> bool {
todo!()
if self.0[0] & 0x1000000 == 0 {
if self.0[0] & 0x2000000 != 0 {
true
} else {
// TODO: properly implement this branch.
false
}
} else {
todo!()
}
}
pub fn is_unk1(&self) -> bool {

View file

@ -57,13 +57,13 @@ impl Ucred {
self.groups[1..].binary_search(&gid).is_ok()
}
pub fn is_unknown1(&self) -> bool {
pub fn is_libkernel_web(&self) -> bool {
// TODO: Refactor this for readability.
let id = self.auth.paid.get().wrapping_add(0xc7ffffffeffffffc);
(id < 0xf) && ((0x6001 >> (id & 0x3f) & 1) != 0)
let val = self.auth.paid.get().wrapping_add(0xc7ffffffeffffffc);
(val < 0xf) && ((0x6001 >> (val & 0x3f) & 1) != 0)
}
pub fn is_unknown2(&self) -> bool {
pub fn is_webprocess_webapp_or_webmas(&self) -> bool {
matches!(
self.auth.paid.get(),
0x380000001000000f | 0x3800000010000013
@ -77,12 +77,36 @@ impl Ucred {
/// See `sceSblACMgrIsJitCompilerProcess` on the PS4 for a reference.
pub fn is_jit_compiler_process(&self) -> bool {
self.auth.caps.is_jit_compiler_process()
let val = self.auth.caps.0[1];
if val >> 0x3e & 1 == 0 {
if val >> 0x38 & 1 != 0 && !todo!() {
true
} else if (self.auth.paid.get() >> 56) == 0x31 && !todo!() {
true
} else {
false
}
} else {
true
}
}
/// See `sceSblACMgrIsJitCompilerProcess` on the PS4 for a reference.
/// See `sceSblACMgrIsJitApplicationProcess` on the PS4 for a reference.
pub fn is_jit_application_process(&self) -> bool {
self.auth.caps.is_jit_application_process()
let val = self.auth.caps.0[1];
if val >> 0x3d & 1 == 0 {
if val >> 0x38 & 1 != 0 && !todo!() {
true
} else if (self.auth.paid.get() >> 56) == 0x31 && !todo!() {
true
} else {
false
}
} else {
true
}
}
/// See `sceSblACMgrIsVideoplayerProcess` on the PS4 for a reference.
@ -97,14 +121,17 @@ impl Ucred {
/// See `sceSblACMgrIsWebcoreProcess` on the PS4 for a reference.
pub fn is_webcore_process(&self) -> bool {
todo!()
let val = self.auth.paid.get().wrapping_add(0xc7ffffffeffffffd);
(val < 0x11) && (0x1d003 >> (val & 0x3f) & 1 != 0)
}
/// See `sceSblACMgrHasSceProgramAttribute` on the PS4 for a reference.
pub fn has_sce_program_attribute(&self) -> bool {
self.auth.attrs.has_sce_program_attribute()
}
/// See `sceSblACMgrHasSceProgramAttribute` on the PS4 for a reference.
/// See `sceSblACMgrIsDebuggableProcess` on the PS4 for a reference.
pub fn is_debuggable_process(&self) -> bool {
self.auth.attrs.is_debuggable_process()
}

View file

@ -35,7 +35,7 @@ privileges! {
/// See https://github.com/freebsd/freebsd-src/blob/release/9.1.0/sys/sys/priv.h for standard
/// FreeBSD privileges.
#[repr(i32)]
#[derive(Clone, Copy, PartialEq, Eq)]
#[derive(PartialEq, Eq)]
pub enum Privilege {
/// Exceed system open files limit.
#[allow(unused)]
@ -57,6 +57,7 @@ privileges! {
/// Currently unknown.
SCE683 = 683,
/// Currently unknown.
#[allow(unused)]
SCE685 = 685,
/// Currently unknown.
SCE686 = 686,

View file

@ -295,11 +295,11 @@ impl Vm {
}
/// See `vm_map_set_name` on the PS4 for a reference.
pub fn mname<N: AsRef<str>>(
pub fn mname(
&self,
addr: *mut u8,
len: usize,
name: N,
name: impl AsRef<str>,
) -> Result<(), MemoryUpdateError> {
let name = name.as_ref();
let sname = CString::new(name);
@ -310,7 +310,7 @@ impl Vm {
|i| i.name != name,
|i| {
if let Ok(name) = &sname {
i.storage.set_name(i.addr, i.len, name).ok();
let _ = i.storage.set_name(i.addr, i.len, name);
}
i.name = name.to_owned();
@ -510,7 +510,7 @@ impl Vm {
// Set storage name if supported.
if let Ok(name) = CString::new(name.as_str()) {
storage.set_name(addr, len, &name).ok();
let _ = storage.set_name(addr, len, &name);
}
Ok(Alloc {