jsonpiler 0.11.0

a Json syntax programming language for Windows
Documentation
use super::mach_o::*;
use crate::prelude::*;
#[expect(clippy::arbitrary_source_item_ordering)]
#[derive(Debug, Clone)]
pub(crate) struct A64LcSegment {
  name: [u8; 16],
  pub vm_addr: u64,
  pub vm_size: u64,
  pub file_off: u64,
  pub file_size: u64,
  max_prot: Protection,
  init_prot: Protection,
  flags: u32,
  sections: Vec<A64LcSection>,
}
#[expect(clippy::arbitrary_source_item_ordering)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct A64LcSection {
  name: [u8; 16],
  addr: u64,
  size: u64,
  offset: u32,
  align: u32,
  flags: u32,
  reserved: [u32; 3],
}
impl A64LcSegment {
  pub(crate) fn dummy(n_sects: usize) -> Self {
    const ___: Protection = Protection { r: false, w: false, e: false };
    Self {
      name: [0u8; 16],
      vm_addr: 0,
      vm_size: 0,
      file_off: 0,
      file_size: 0,
      max_prot: ___,
      init_prot: ___,
      flags: 0,
      sections: vec![
        A64LcSection {
          name: [0u8; 16],
          addr: 0,
          size: 0,
          offset: 0,
          align: 0,
          flags: 0,
          reserved: [0; 3],
        };
        n_sects
      ],
    }
  }
  pub(crate) fn lc_segment(&self) -> ErrOR<Vec<u8>> {
    const LC_SEGMENT_64: u32 = 0x19;
    let total = self.sizeof_cmd()?;
    let mut bytes = Vec::with_capacity(total as usize);
    extend!(
      bytes,
      LC_SEGMENT_64.to_le_bytes(),
      total.to_le_bytes(),
      self.name,
      self.vm_addr.to_le_bytes(),
      self.sizeof_vm()?.to_le_bytes(),
      self.file_off.to_le_bytes(),
      self.sizeof_file()?.to_le_bytes(),
      self.max_prot.to_le_bytes(),
      self.init_prot.to_le_bytes(),
      len_u32(&self.sections)?.to_le_bytes(),
      self.flags.to_le_bytes(),
    );
    for sect in &self.sections {
      extend!(
        bytes,
        sect.name,
        self.name,
        sect.addr.to_le_bytes(),
        sect.size.to_le_bytes(),
        sect.offset.to_le_bytes(),
        sect.align.to_le_bytes(),
        [0; 8],
        sect.flags.to_le_bytes(),
        sect.reserved[0].to_le_bytes(),
        sect.reserved[1].to_le_bytes(),
        sect.reserved[2].to_le_bytes()
      );
    }
    Ok(bytes)
  }
}
impl A64LcSegment {
  pub(crate) fn add(
    &mut self,
    name: &[u8],
    size: u64,
    align: u32,
    flags: u32,
    reserved: [u32; 3],
    bss: bool,
  ) -> ErrOR<()> {
    let offset = align_up_u64(self.file_off + self.file_size, 1 << align)?;
    let addr = align_up_u64(self.vm_addr + self.vm_size, 1 << align)?;
    self.sections.push(A64LcSection {
      name: seg_sect_name(name),
      addr,
      size,
      offset: u32::try_from(offset)?,
      align,
      flags,
      reserved,
    });
    if !bss {
      self.file_size += size;
    }
    self.vm_size += size;
    Ok(())
  }
}
impl A64LcSegment {
  pub(crate) fn next(
    &self,
    name: &[u8],
    size: Option<u64>,
    prot: Protection,
    flags: u32,
  ) -> ErrOR<Self> {
    let file_off = self.file_off + self.sizeof_file()?;
    let vm_addr = self.vm_addr + self.sizeof_vm()?;
    Ok(Self {
      name: seg_sect_name(name),
      vm_addr,
      vm_size: size.unwrap_or(0),
      file_off,
      file_size: size.unwrap_or(0),
      max_prot: prot,
      init_prot: prot,
      flags,
      sections: vec![],
    })
  }
  pub(crate) fn page_zero() -> Self {
    Self {
      name: seg_sect_name(b"PAGEZERO"),
      vm_addr: 0,
      vm_size: A64_TEXT_ADDR,
      file_off: 0,
      file_size: 0,
      max_prot: Protection::default(),
      init_prot: Protection::default(),
      flags: 0,
      sections: vec![],
    }
  }
  pub(crate) fn sizeof_cmd(&self) -> ErrOR<u32> {
    Ok(0x48 + len_u32(&self.sections)? * 0x50)
  }
  pub(crate) fn sizeof_file(&self) -> ErrOR<u64> {
    align_up_u64(self.file_size, u64::from(A64_SEG_ALIGN))
  }
  pub(crate) fn sizeof_vm(&self) -> ErrOR<u64> {
    align_up_u64(self.vm_size, u64::from(A64_SEG_ALIGN))
  }
}
pub(crate) fn seg_sect_name(name: &[u8]) -> [u8; 16] {
  let mut buf = [0u8; 16];
  let len = name.len().min(14);
  buf[0..2].copy_from_slice(b"__");
  buf[2..len + 2].copy_from_slice(&name[..len]);
  buf
}