From f82dfe38e796b7ae074e7547d15a7b624c6ce0a7 Mon Sep 17 00:00:00 2001 From: Joakim Hulthe Date: Fri, 16 Feb 2024 13:49:11 +0100 Subject: [PATCH] Parse sectoin header flags --- Cargo.lock | 45 ++++++++++++++++++-- Cargo.toml | 2 + rust-toolchain.toml | 2 - src/ints.rs | 8 ++-- src/main.rs | 11 +++++ src/section_header.rs | 97 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 156 insertions(+), 9 deletions(-) delete mode 100644 rust-toolchain.toml create mode 100644 src/section_header.rs diff --git a/Cargo.lock b/Cargo.lock index 43504d6..bc145a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -113,6 +113,15 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +dependencies = [ + "bytemuck", +] + [[package]] name = "brownstone" version = "3.0.0" @@ -311,6 +320,7 @@ dependencies = [ name = "elf" version = "0.1.0" dependencies = [ + "bitflags 2.4.2", "bytemuck", "clap", "color-eyre", @@ -319,6 +329,7 @@ dependencies = [ "rend", "serde", "serde_json", + "strum", "symbolic", ] @@ -532,7 +543,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfb67c6dd0fa9b00619c41c5700b6f92d5f418be49b45ddb9970fbd4569df3c8" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -625,7 +636,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4e89a9f2f40b2389ba6da0814c8044bf942bece03dffa1514f84e3b525f4f9a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "elsa", "maybe-owned", "pdb", @@ -751,7 +762,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -799,6 +810,12 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "ryu" version = "1.0.16" @@ -921,6 +938,28 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strum" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.48", +] + [[package]] name = "symbolic" version = "12.8.0" diff --git a/Cargo.toml b/Cargo.toml index 760a523..b95d501 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +bitflags = { version = "2.4.2", features = ["bytemuck", "std"] } bytemuck = "1.14.0" clap = { version = "4.4.18", features = ["derive"] } color-eyre = "0.6.2" @@ -14,4 +15,5 @@ rand = "0.8.5" rend = { version = "0.4.1", features = ["bytemuck"] } serde = { version = "1.0.196", features = ["derive"] } serde_json = "1.0.113" +strum = { version = "0.26.1", features = ["derive"] } symbolic = { version = "12.8.0", features = ["demangle"] } diff --git a/rust-toolchain.toml b/rust-toolchain.toml deleted file mode 100644 index 5d56faf..0000000 --- a/rust-toolchain.toml +++ /dev/null @@ -1,2 +0,0 @@ -[toolchain] -channel = "nightly" diff --git a/src/ints.rs b/src/ints.rs index 3565683..39ccaa6 100644 --- a/src/ints.rs +++ b/src/ints.rs @@ -12,7 +12,7 @@ pub struct BigEndian; pub struct LittleEndian; pub trait Decode: Copy + Zeroable + Pod { - type Native: Debug + Copy + TryInto + TryInto + Into; + type Native: Debug + Copy + TryInto + TryInto + Into + Serialize; fn to_native(self) -> Self::Native; } @@ -114,7 +114,7 @@ where where S: serde::Serializer, { - format!("{:?}", self.to_native()).serialize(serializer) + self.to_native().serialize(serializer) } } @@ -126,7 +126,7 @@ where where S: serde::Serializer, { - format!("{:?}", self.to_native()).serialize(serializer) + self.to_native().serialize(serializer) } } @@ -138,6 +138,6 @@ where where S: serde::Serializer, { - format!("{:?}", self.to_native()).serialize(serializer) + self.to_native().serialize(serializer) } } diff --git a/src/main.rs b/src/main.rs index f946a09..45cffb8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,11 @@ mod ints; mod output; +mod section_header; mod structs; use crate::{ output::Output, + section_header::SectionHeaderFlags, structs::{ BigEndian32, BigEndian64, ElfConfig, ElfHeader1, ElfHeader2, LittleEndian32, LittleEndian64, SectionHeaderEntry, SymbolTableEntry, @@ -113,7 +115,16 @@ macro_rules! parse_elf { unreachable!() }; + + let flags = SectionHeaderFlags::try_from(u64::from(entry.sh_flags.to_native())) + .wrap_err(eyre!("invalid sh_flags in section {name:?}"))?; + + let flags: Vec<_> = flags.iter() + .map(|flag| format!("{flag:?}")) + .collect(); + fields.insert("name".to_string(), Value::String(name.to_string())); + fields.insert("flags".to_string(), flags.into()); section_header_entries_with_names.push(entry_json); } let _ = out.write("sections", §ion_header_entries_with_names); diff --git a/src/section_header.rs b/src/section_header.rs new file mode 100644 index 0000000..925be88 --- /dev/null +++ b/src/section_header.rs @@ -0,0 +1,97 @@ +use eyre::bail; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[repr(transparent)] +pub struct SectionHeaderFlags(u64); + +const ALL_FLAGS: [SectionHeaderFlag; 14] = [ + SectionHeaderFlag::Write, + SectionHeaderFlag::Alloc, + SectionHeaderFlag::Execinstr, + SectionHeaderFlag::Merge, + SectionHeaderFlag::Strings, + SectionHeaderFlag::InfoLink, + SectionHeaderFlag::LinkOrder, + SectionHeaderFlag::OsNonconforming, + SectionHeaderFlag::Group, + SectionHeaderFlag::Tls, + SectionHeaderFlag::Maskos, + SectionHeaderFlag::Maskproc, + SectionHeaderFlag::Ordered, + SectionHeaderFlag::Exclude, +]; + +fn flag_bitmask() -> u64 { + ALL_FLAGS + .iter() + .copied() + .fold(0u64, |acc, e| acc | e as u64) +} + +#[repr(u64)] +#[derive(Clone, Copy, Debug)] +pub enum SectionHeaderFlag { + /// Writable + Write = 0x1, + + /// Occupies memory during execution + Alloc = 0x2, + + /// Executable + Execinstr = 0x4, + + /// Might be merged + Merge = 0x10, + + /// Contains null-terminated strings + Strings = 0x20, + + /// 'sh_info' contains SHT index + InfoLink = 0x40, + + /// Preserve order after combining + LinkOrder = 0x80, + + /// Non-standard OS specific handling required + OsNonconforming = 0x100, + + /// Section is member of a group + Group = 0x200, + + /// Section hold thread-local data + Tls = 0x400, + + /// OS-specific + Maskos = 0x0FF00000, + + /// Processor-specific + Maskproc = 0xF0000000, + + /// Special ordering requirement (Solaris) + Ordered = 0x4000000, + + /// Section is excluded unless referenced or allocated (Solaris) + Exclude = 0x8000000, +} + +impl TryFrom for SectionHeaderFlags { + type Error = eyre::Error; + + fn try_from(value: u64) -> Result { + if value & !flag_bitmask() != 0 { + bail!("Invalid section header flag, unknown bit pattern: 0x{value:x}"); + } + + Ok(SectionHeaderFlags(value)) + } +} + +impl SectionHeaderFlags { + /// Iterate over set flags + pub fn iter(&self) -> impl Iterator + '_ { + ALL_FLAGS + .iter() + .copied() + .filter(|&flag| (self.0 & flag as u64) != 0) + } +}