summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/main.rs68
-rw-r--r--src/structs.rs133
2 files changed, 181 insertions, 20 deletions
diff --git a/src/main.rs b/src/main.rs
index 5e6a07c..6032500 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,7 +1,9 @@
 // #![allow(incomplete_features)]
 // #![feature(unsized_locals)]
 mod structs;
-use crate::structs::{ElfHeader, ElfSectionHeader, ElfSectionType, ElfSymbol};
+use crate::structs::{
+    ElfHeader, ElfProgramHeader, ElfProgramType, ElfSectionHeader, ElfSectionType, ElfSymbol,
+};
 use std::io::Read;
 
 #[repr(C)]
@@ -10,7 +12,9 @@ struct Elf {
     header: &'static ElfHeader,
     sections: &'static [ElfSectionHeader],
     symbols: &'static [ElfSymbol],
-    strtab: *const u8,
+    programs: &'static [ElfProgramHeader],
+    shstrtab: *const u8,
+    start: *const u8,
 }
 
 impl Elf {
@@ -25,17 +29,25 @@ impl Elf {
             )
         };
 
-        let strtab = unsafe {
+        let shstrtab = unsafe {
             bytes
                 .as_ptr()
                 .add((&sections[header.shstrndx as usize]).offset as usize)
         };
 
+        let programs = unsafe {
+            std::slice::from_raw_parts(
+                bytes.as_ptr().add(header.phoff as usize) as *const ElfProgramHeader,
+                header.phnum as usize,
+            )
+        };
+        // dbg!(program);
+
         let symtab = sections
             .iter()
             .find(|&&sec| sec.r#type == ElfSectionType::SymTab)
             .expect("No symbol table!");
-        //dbg!(&sections[symtab.link as usize]);
+        // //dbg!(&sections[symtab.link as usize]);
         let symstrtab = &sections[symtab.link as usize];
         let symbols = unsafe {
             std::slice::from_raw_parts(
@@ -48,26 +60,28 @@ impl Elf {
         // .iter()
         // .filter(|sym| sym.shndx != 0)
         // .filter_map(|sym| unsafe {
-            // std::ffi::CStr::from_ptr(std::ptr::addr_of!(symstrtab).add(sym.name as usize) as *const i8).to_str().ok()
+        // std::ffi::CStr::from_ptr(std::ptr::addr_of!(symstrtab).add(sym.name as usize) as *const i8).to_str().ok()
         // })
         // .filter(|name| name.len() > 1)
         // .collect();
         // dbg!(symbols);
-        for sym in symbols {
-        //     dbg!(sym);
-            let name = unsafe {
-                std::ffi::CStr::from_ptr(bytes.as_ptr().add(symstrtab.offset as usize).add(sym.name as usize) as *const i8)
-                    .to_str()
-                    .unwrap_or("")
-            };
-            dbg!(name);
-        }
+        // for sym in symbols {
+        // // //     dbg!(sym);
+        //     let name = unsafe {
+        //        std::ffi::CStr::from_ptr(bytes.as_ptr().add(symstrtab.offset as usize).add(sym.name as usize) as *const i8)
+        //             .to_str()
+        //             .unwrap_or("")
+        //     };
+        //     dbg!(name);
+        // }
 
         Elf {
             header,
             sections,
             symbols,
-            strtab,
+            programs,
+            shstrtab,
+            start: bytes.as_ptr(),
         }
     }
 }
@@ -86,7 +100,7 @@ impl std::fmt::Display for Elf {
 
         for (i, section) in self.sections.iter().enumerate() {
             let name = unsafe {
-                std::ffi::CStr::from_ptr(self.strtab.add(section.name as usize) as *const i8)
+                std::ffi::CStr::from_ptr(self.shstrtab.add(section.name as usize) as *const i8)
                     .to_str()
                     .expect("Bad section name")
             };
@@ -101,7 +115,25 @@ impl std::fmt::Display for Elf {
             "  L (link order), O (extra OS processing required), G (group), T (TLS),\n",
         )?;
         formatter.write_str("  C (compressed), x (unknown), o (OS specific), E (exclude),\n")?;
-        formatter.write_str("  D (mbind), l (large), p (processor specific)\n")?;
+        formatter.write_str("  D (mbind), l (large), p (processor specific)\n\n")?;
+
+        formatter.write_str("Program Headers:\n")?;
+        formatter.write_str("  Type           Offset             VirtAddr           PhysAddr\n")?;
+        formatter
+            .write_str("                 FileSiz            MemSiz              Flags  Align\n")?;
+        for program in self.programs {
+            formatter.write_fmt(format_args!("  {}\n", program));
+            if program.r#type == ElfProgramType::Interp {
+                let interpreter = unsafe {
+                    std::ffi::CStr::from_ptr(self.start.add(program.offset as usize) as *const i8)
+                        .to_str()
+                        .expect("Bad interpreter name")
+                };
+                formatter.write_fmt(format_args!(
+                    "      [Requesting program interpreter: {interpreter}]\n"
+                ));
+            }
+        }
         Ok(())
     }
 }
@@ -117,7 +149,7 @@ fn main() {
         buffer
     };
     let elf = Elf::new(&buffer[..]);
-    // println!("{}", elf);
+    println!("{}", elf);
 
     // dbg!(symtab);
 }
diff --git a/src/structs.rs b/src/structs.rs
index f5c8140..673ae35 100644
--- a/src/structs.rs
+++ b/src/structs.rs
@@ -323,7 +323,7 @@ pub struct ElfSectionHeader {
 impl std::fmt::Display for ElfSectionHeader {
     fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
         formatter.write_fmt(format_args!(
-            "{: <16} {:0>16x} {:0>8x}\n       {:0>16x} {:0>16x} {: ^10} {: <5} {: <5} {}",
+            "{: <16} {:0>16x} {:0>8x}\n       {:0>16x} {:0>16x}   {: <10} {: <5} {: <5} {}",
             self.r#type,
             self.addr,
             self.offset,
@@ -451,7 +451,31 @@ bitflags! {
 // https://github.com/llvm-mirror/llvm/blob/2c4ca6832fa6b306ee6a7010bfb80a3f2596f824/tools/llvm-readobj/ELFDumper.cpp#L1176
 impl std::fmt::Display for ElfSectionFlags {
     fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
-        "  A".fmt(formatter);
+        format!(
+            "{}{}{}",
+            {
+                if self.contains(ElfSectionFlags::WRITE) {
+                    "W"
+                } else {
+                    ""
+                }
+            },
+            {
+                if self.contains(ElfSectionFlags::ALLOC) {
+                    "A"
+                } else {
+                    ""
+                }
+            },
+            {
+                if self.contains(ElfSectionFlags::EXEC) {
+                    "X"
+                } else {
+                    ""
+                }
+            }
+        )
+        .fmt(formatter);
         Ok(())
     }
 }
@@ -502,3 +526,108 @@ pub struct ElfSymbol {
     /// size.
     pub size: u64,
 }
+
+#[derive(Debug)]
+#[repr(C)]
+pub struct ElfProgramHeader {
+    pub r#type: ElfProgramType,
+    pub flags: ElfProgramFlags,
+    pub offset: u64,
+    pub vaddr: u64,
+    pub paddr: u64,
+    pub filesz: u64,
+    pub memsz: u64,
+    pub align: u64,
+}
+
+impl std::fmt::Display for ElfProgramHeader {
+    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
+        formatter.write_fmt(format_args!(
+            "{: <14} {:#016x} {:#016x} {:#016x}\n                 {:#016x} {:#016x}   {: <10} {:#08x}",
+            self.r#type,
+			self.offset,
+            self.vaddr,
+            self.paddr,
+            self.filesz,
+            self.memsz,
+            self.flags,
+            self.align,
+        ))?;
+        Ok(())
+    }
+}
+
+#[derive(PartialEq,Debug)]
+#[repr(u32)]
+pub enum ElfProgramType {
+    /// This value marks the section header as inactive.
+    /// It does not have an associated section.  Other
+    /// members of the section header have undefined
+    /// values.
+    PHDR = 6,
+    Interp = 3,
+    Load = 1,
+    Dynamic = 2,
+    Note = 4,
+
+    GnuProperty = 0x6474E553,
+    GnuEhFrame = 0x6474E550,
+    GnuStack = 0x6474E551,
+    GnuRelro = 0x6474E552,
+}
+
+impl std::fmt::Display for ElfProgramType {
+    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
+        match self {
+            ElfProgramType::PHDR => "PHDR".fmt(formatter),
+            ElfProgramType::Interp => "INTERP".fmt(formatter),
+            ElfProgramType::Note => "NOTE".fmt(formatter),
+            ElfProgramType::Load => "LOAD".fmt(formatter),
+            ElfProgramType::Dynamic => "DYNAMIC".fmt(formatter),
+            ElfProgramType::GnuProperty => "GNU_PROPERTY".fmt(formatter),
+            ElfProgramType::GnuEhFrame => "GNU_EH_FRAME".fmt(formatter),
+            ElfProgramType::GnuStack => "GNU_STACK".fmt(formatter),
+            ElfProgramType::GnuRelro => "GNU_RELRO".fmt(formatter),
+        }
+    }
+}
+
+bitflags! {
+    #[derive(Debug)]
+    pub struct ElfProgramFlags: u32 {
+        const EXEC = 0x1;
+        const WRITE = 0x2;
+        const READ = 0x4;
+    }
+}
+
+impl std::fmt::Display for ElfProgramFlags {
+    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
+        format!(
+            "{}{}{}",
+            {
+                if self.contains(ElfProgramFlags::READ) {
+                    "R"
+                } else {
+                    " "
+                }
+            },
+            {
+                if self.contains(ElfProgramFlags::WRITE) {
+                    "W"
+                } else {
+                    " "
+                }
+            },
+            {
+                if self.contains(ElfProgramFlags::EXEC) {
+                    "E"
+                } else {
+                    " "
+                }
+            }
+        )
+        .fmt(formatter);
+        Ok(())
+    }
+}
\ No newline at end of file