Skip to content

Commit

Permalink
Merge pull request #3 from CuriousTommy/improve_lcthread_formatting
Browse files Browse the repository at this point in the history
Improve LcThread Formatting
  • Loading branch information
Arsynth committed Dec 10, 2023
2 parents 45866cf + db4d398 commit 96f3365
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 28 deletions.
15 changes: 15 additions & 0 deletions src/commands/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ impl DefaultHandler {
match variant {
LcVariant::Segment32(seg) => self.handle_segment_command(seg, level),
LcVariant::Segment64(seg) => self.handle_segment_command(seg, level),
LcVariant::Thread(thread) => self.handle_thread_flavor(thread, level),
_ => (),
}
}
Expand All @@ -112,4 +113,18 @@ impl DefaultHandler {
.out_dashed_field(&field.name, &field.value, level + 1);
}
}

fn handle_thread_flavor(&self, thread: LcThread, level: usize) {
self.printer
.out_dashed_field("Flavors", "", level);

for thread_flavor in thread.flavor_iterator() {
for field in thread_flavor.all_fields() {
self.printer
.out_dashed_field(&field.name, &field.value, level + 1);
}

self.printer.out_tile(level + 1);
}
}
}
108 changes: 80 additions & 28 deletions src/types/load_command/thread_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,28 @@ use std::mem::size_of;
use crate::auto_enum_fields::*;
use schnauzer_derive::AutoEnumFields;

const LC_THREAD_FLAVOR_HEADER_SIZE: usize = size_of::<u32>() + size_of::<u32>();
// LC_THREAD_FLAVOR_HEADER_SIZE = sizeof(thread_command.flavor) + sizeof(thread_command.count)
const LC_THREAD_FLAVOR_HEADER_SIZE: u32 = size_of::<u32>() as u32 + size_of::<u32>() as u32;

/// `thread_command`
#[repr(C)]
#[derive(AutoEnumFields,Debug)]
pub struct LcThread {
pub flavors: Vec<LcThreadFlavor>
reader: RcReader,

cmdsize: u32,
base_offset: usize,
endian: scroll::Endian,
}

impl LcThread {
pub(super) fn parse(reader: RcReader, cmdsize: u32, base_offset: usize, endian: scroll::Endian) -> Result<Self> {
Ok(LcThread { reader, cmdsize, base_offset, endian })
}

pub fn flavor_iterator(&self) -> FlavorIterator {
FlavorIterator::new(self.reader.clone(), self.cmdsize, self.base_offset, self.endian)
}
}

#[repr(C)]
Expand All @@ -30,45 +45,35 @@ pub struct LcThreadFlavor {
state_offset: u64
}

impl LcThread {
pub(super) fn parse(reader: RcReader, cmdsize: u32, base_offset: usize, endian: scroll::Endian) -> Result<Self> {
let mut flavors = Vec::new();

let mut flavor_offset = base_offset;
loop {
let flavor = LcThreadFlavor::parse(&reader, flavor_offset, endian)?;
if flavor.flavor != 0 && flavor.count != 0 {
flavor_offset += LC_THREAD_FLAVOR_HEADER_SIZE + flavor.count as usize * size_of::<u32>();
flavors.push(flavor);

if flavor_offset < base_offset + cmdsize as usize {
continue;
}
}

break;
}

Ok(LcThread { flavors })
}
}

impl LcThreadFlavor {
pub(super) fn parse(reader: &RcReader, base_offset: usize, endian: scroll::Endian) -> Result<Self> {
pub(super) fn parse(reader: &RcReader, base_offset: usize, endian: scroll::Endian) -> Result<Option<Self>> {
let mut reader_mut = reader.borrow_mut();
reader_mut.seek(SeekFrom::Start(base_offset as u64))?;

let flavor: u32 = reader_mut.ioread_with(endian)?;
let count: u32 = reader_mut.ioread_with(endian)?;

let state_offset = reader_mut.stream_position()?;

Ok(LcThreadFlavor { flavor, count, state_offset })

if flavor == 0 && count == 0 {
// We reached the end of the list
return Ok(None);
}

Ok(Some(LcThreadFlavor { flavor, count, state_offset }))
}

pub fn get_state_offset(&self) -> u64 {
self.state_offset
}

fn calculate_flavor_size(&self) -> u32 {
// the size of a flavor is based on the following:
// flavor_size = LC_THREAD_FLAVOR_HEADER_SIZE + sizeof(thread_command.state)

// count * sizeof(uint32_t) is equalivent to sizeof(thread_command.state)
LC_THREAD_FLAVOR_HEADER_SIZE + self.count * size_of::<u32>() as u32
}
}

impl Debug for LcThreadFlavor {
Expand All @@ -78,4 +83,51 @@ impl Debug for LcThreadFlavor {
.field("count", &self.count)
.finish()
}
}

pub struct FlavorIterator {
reader: RcReader,
base_offset: usize,
cmdsize: u32,
endian: scroll::Endian,

current: u32,
}

impl FlavorIterator {
fn new(reader: RcReader, cmdsize: u32, base_offset: usize, endian: scroll::Endian) -> Self {
FlavorIterator {
reader,
base_offset,
cmdsize,
endian,
current: 0,
}
}
}

impl Iterator for FlavorIterator {
type Item = LcThreadFlavor;

fn next(&mut self) -> Option<Self::Item> {
if self.current >= self.cmdsize {
return None;
}

let offset = self.base_offset + self.current as usize;

match LcThreadFlavor::parse(&self.reader, offset as usize, self.endian) {
Ok(Some(lc_thread_flavor)) => {
self.current += lc_thread_flavor.calculate_flavor_size();
Some(lc_thread_flavor)
},

Ok(None) => {
self.current = self.cmdsize;
None
},

Err(_) => None,
}
}
}

0 comments on commit 96f3365

Please sign in to comment.