binkit 0.1.1

A modular toolbox for analyzing, disassembling, and patching binary formats
Documentation
use crate::traits::header_field::HeaderField;
use crate::utils::endian::Endian;
use crate::utils::read_cstring::read_cstring;

use super::types::{elf64_header::Elf64Header, elf64_program_header::Elf64ProgramHeader, elf64_section_header::Elf64SectionHeader};
use tabled::{Table, Tabled};
use tabled::settings::{Settings, Style};
use anyhow::{Result};

pub fn print_header(header: &Elf64Header, endian: &Endian) {
    #[derive(Tabled)]
    struct HeaderField<'a> {
        name: &'a str,
        describe: String,
    }

    let fields = vec![
        HeaderField { name: "e_ident",  describe: header.e_ident.describe(endian) },
        HeaderField { name: "e_type",  describe: header.e_type.describe(endian) },
        HeaderField { name: "e_machine",  describe: header.e_machine.describe(endian) },
        HeaderField { name: "e_version",  describe: header.e_version.describe(endian) },
        HeaderField { name: "e_entry",  describe: header.e_entry.describe(endian) },
        HeaderField { name: "e_phoff",  describe: header.e_phoff.describe(endian) },
        HeaderField { name: "e_shoff",  describe: header.e_shoff.describe(endian) },
        HeaderField { name: "e_flags",  describe: header.e_flags.describe(endian) },
        HeaderField { name: "e_ehsize",  describe: header.e_ehsize.describe(endian) },
        HeaderField { name: "e_phentsize",  describe: header.e_phentsize.describe(endian) },
        HeaderField { name: "e_phnum",  describe: header.e_phnum.describe(endian) },
        HeaderField { name: "e_shentsize",  describe: header.e_shentsize.describe(endian) },
        HeaderField { name: "e_shnum",  describe: header.e_shnum.describe(endian) },
        HeaderField { name: "e_shstrndx",  describe: header.e_shstrndx.describe(endian) },
    ];

    let table_config = Settings::default()
        .with(Style::modern());
    let table = Table::new(fields).with(table_config).to_string();
    println!("Elf header:");
    println!("{table}");
}

pub fn print_program_headers(phs: &[Elf64ProgramHeader], endian: &Endian) {
    #[derive(Tabled)]
    #[allow(clippy::struct_field_names)]
    struct ProgramHeaderFields {
        p_type: String,
        p_offset: String,
        p_vaddr: String,
        p_paddr: String,
        p_filesz: String,
        p_memsz: String,
        p_flags: String,
        p_align: String,
    }

    let table_config = Settings::default()
        .with(Style::modern());

    let mut fields: Vec<ProgramHeaderFields> = Vec::with_capacity(phs.len());

    for ph in phs {
        fields.push(
            ProgramHeaderFields { 
                p_type: ph.p_type.describe(endian),
                p_offset: ph.p_offset.describe(endian),
                p_vaddr: ph.p_vaddr.describe(endian),
                p_paddr: ph.p_paddr.describe(endian),
                p_filesz: ph.p_filesz.describe(endian),
                p_memsz: ph.p_memsz.describe(endian),
                p_flags: ph.p_flags.describe(endian),
                p_align: ph.p_align.describe(endian)
            }
        );
    }

    let table = Table::new(fields).with(table_config).to_string();

    println!("\nProgram headers:");
    println!("{table}");
}

pub fn print_section_headers(shs: &[Elf64SectionHeader], endian: &Endian, strtab: &[u8]) -> Result<()> {
    #[derive(Tabled)]
    #[allow(clippy::struct_field_names)]
    struct SectionHeaderFields {
        sh_name: String,
        sh_type: String,
        sh_flags: String,
        sh_addr: String,
        sh_offset: String,
        sh_size: String,
        sh_link: String,
        sh_info: String,
        sh_addralign: String,
        sh_entsize: String,
    }

    let table_config = Settings::default()
        .with(Style::modern());

    let mut fields: Vec<SectionHeaderFields> = Vec::with_capacity(shs.len());

    for sh in shs {
        let sh_name = read_cstring(&strtab[sh.sh_name.value(endian) as usize..])?;
        fields.push(
            SectionHeaderFields { 
                sh_name: sh_name.to_string(),
                sh_type: sh.sh_type.describe(endian),
                sh_flags: sh.sh_flags.describe(endian),
                sh_addr: sh.sh_addr.describe(endian),
                sh_offset: sh.sh_offset.describe(endian),
                sh_size: sh.sh_size.describe(endian),
                sh_link: sh.sh_link.describe(endian),
                sh_info: sh.sh_info.describe(endian),
                sh_addralign: sh.sh_addralign.describe(endian),
                sh_entsize: sh.sh_entsize.describe(endian)
            }
        );
    }

    let table = Table::new(fields).with(table_config).to_string();

    println!("\nSection headers:");
    println!("{table}");
    Ok(())
}