summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock9
-rw-r--r--Cargo.toml1
-rw-r--r--flake.lock79
-rw-r--r--flake.nix91
-rw-r--r--src/main.rs47
-rw-r--r--src/structs.rs426
7 files changed, 439 insertions, 215 deletions
diff --git a/.gitignore b/.gitignore
index 2d5df85..7343d41 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 /target
 .direnv
+/result
diff --git a/Cargo.lock b/Cargo.lock
index b245edb..8f627af 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,5 +3,14 @@
 version = 3
 
 [[package]]
+name = "bitflags"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1"
+
+[[package]]
 name = "elf"
 version = "0.1.0"
+dependencies = [
+ "bitflags",
+]
diff --git a/Cargo.toml b/Cargo.toml
index 4b0f643..aad63f6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,3 +6,4 @@ edition = "2021"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
+bitflags = "2.0.2"
diff --git a/flake.lock b/flake.lock
index 24fa37e..ab83f17 100644
--- a/flake.lock
+++ b/flake.lock
@@ -1,78 +1,79 @@
 {
   "nodes": {
-    "fenix": {
+    "flake-parts": {
       "inputs": {
-        "nixpkgs": [
+        "nixpkgs-lib": [
           "nixpkgs"
-        ],
-        "rust-analyzer-src": "rust-analyzer-src"
+        ]
       },
       "locked": {
-        "lastModified": 1676960692,
-        "narHash": "sha256-DRIqvgJHPgxfkWSsMEJv7w6BeyXv0kMx858l9+i5w3I=",
-        "owner": "nix-community",
-        "repo": "fenix",
-        "rev": "e9920200ddfa23d811a620750316c48512e46240",
+        "lastModified": 1678379998,
+        "narHash": "sha256-TZdfNqftHhDuIFwBcN9MUThx5sQXCTeZk9je5byPKRw=",
+        "owner": "hercules-ci",
+        "repo": "flake-parts",
+        "rev": "c13d60b89adea3dc20704c045ec4d50dd964d447",
         "type": "github"
       },
       "original": {
-        "owner": "nix-community",
-        "repo": "fenix",
+        "owner": "hercules-ci",
+        "repo": "flake-parts",
         "type": "github"
       }
     },
-    "flake-utils": {
+    "nixpkgs": {
       "locked": {
-        "lastModified": 1676283394,
-        "narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073",
+        "lastModified": 1679319606,
+        "narHash": "sha256-wyEMIZB6BnsmJWInEgDZu66hXVMGJEZFl5uDsn27f9M=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "8bc6945b1224a1cfa679d6801580b1054dba1a5c",
         "type": "github"
       },
       "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
+        "owner": "NixOS",
+        "ref": "nixpkgs-unstable",
+        "repo": "nixpkgs",
         "type": "github"
       }
     },
-    "nixpkgs": {
+    "nixpkgs_2": {
       "locked": {
-        "lastModified": 1659446231,
-        "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=",
-        "owner": "NixOS",
+        "lastModified": 1677932085,
+        "narHash": "sha256-+AB4dYllWig8iO6vAiGGYl0NEgmMgGHpy9gzWJ3322g=",
+        "owner": "nixos",
         "repo": "nixpkgs",
-        "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d",
+        "rev": "3c5319ad3aa51551182ac82ea17ab1c6b0f0df89",
         "type": "github"
       },
       "original": {
-        "owner": "NixOS",
-        "ref": "nixos-21.11",
+        "owner": "nixos",
+        "ref": "nixos-unstable",
         "repo": "nixpkgs",
         "type": "github"
       }
     },
     "root": {
       "inputs": {
-        "fenix": "fenix",
-        "flake-utils": "flake-utils",
-        "nixpkgs": "nixpkgs"
+        "flake-parts": "flake-parts",
+        "nixpkgs": "nixpkgs",
+        "treefmt-nix": "treefmt-nix"
       }
     },
-    "rust-analyzer-src": {
-      "flake": false,
+    "treefmt-nix": {
+      "inputs": {
+        "nixpkgs": "nixpkgs_2"
+      },
       "locked": {
-        "lastModified": 1676584162,
-        "narHash": "sha256-8h0sV0fmMSB7KydJJD5Iz1kJxR3YzYa3iJ71VD2zePk=",
-        "owner": "rust-lang",
-        "repo": "rust-analyzer",
-        "rev": "a6603fc21d50b3386a488c96225b2d1fd492e533",
+        "lastModified": 1678901796,
+        "narHash": "sha256-9myDjq948gHbiv16HnFQZaswQEpNodE/CuGCfDNnv/g=",
+        "owner": "numtide",
+        "repo": "treefmt-nix",
+        "rev": "0f560a84215e79facd2833b20bfdc2033266f126",
         "type": "github"
       },
       "original": {
-        "owner": "rust-lang",
-        "ref": "nightly",
-        "repo": "rust-analyzer",
+        "owner": "numtide",
+        "repo": "treefmt-nix",
         "type": "github"
       }
     }
diff --git a/flake.nix b/flake.nix
index fafb6ca..b8230de 100644
--- a/flake.nix
+++ b/flake.nix
@@ -1,64 +1,47 @@
-
 {
-  # XXX: Change project description
-  description = "Rust project";
-
   inputs = {
-    nixpkgs.url = "github:NixOS/nixpkgs/nixos-21.11";
-    fenix = {
-      url = "github:nix-community/fenix";
-      inputs.nixpkgs.follows = "nixpkgs";
-    };
-    flake-utils.url = "github:numtide/flake-utils";
+    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
+    flake-parts = { url = "github:hercules-ci/flake-parts"; inputs.nixpkgs-lib.follows = "nixpkgs"; };
+    treefmt-nix.url = "github:numtide/treefmt-nix";
   };
 
-  outputs = { self, nixpkgs, fenix, flake-utils }:
-    flake-utils.lib.eachDefaultSystem
-      (system:
-        let
-          pkgs = nixpkgs.legacyPackages."${system}";
+  outputs = inputs:
+    inputs.flake-parts.lib.mkFlake { inherit inputs; } {
+      systems = [ "x86_64-linux" ];
+      imports = [ inputs.treefmt-nix.flakeModule ];
 
-          # XXX: Change target platform
-          rust-target = "x86_64-unknown-linux-gnu";
-          rust-toolchain = with fenix.packages."${system}"; let
-            rust-toolchain-spec = {
-              # XXX: Change compiler version
-              # see `toolchainOf` https://github.com/nix-community/fenix
-              # for supported options
-              channel = "nightly";
-              sha256 = "sha256-xdqN1O2O9GJ+Jg/Gsdj2Hra1KFQIQpAu4vGczSBsLDo=";
-            };
-            # Toolchain for the builder
-            host-toolchain = toolchainOf rust-toolchain-spec;
-            # Toolchain for the platform where the binary will run
-            # target-toolchain = targets."${rust-target}".toolchainOf rust-toolchain-spec;
-          in
-          combine [
-            # Build tools are taken from the host
-            host-toolchain.rustc
-            host-toolchain.cargo
-            host-toolchain.clippy
-            host-toolchain.rust-docs
-            # Standard library is taken from the target
-            host-toolchain.rust-std
-            host-toolchain.rust-src
-          ];
+      perSystem = { pkgs, lib, config, ... }:
+        let
+          src = lib.sourceFilesBySuffices inputs.self [ ".rs" ".toml" "Cargo.lock" ];
+          inherit (lib.importTOML (src + "/Cargo.toml")) package;
         in
         {
-          devShells.default = pkgs.mkShell {
-            # XXX: Change to project name
-            name = "rust-project";
+          packages = {
+            ${package.name} = pkgs.rustPlatform.buildRustPackage {
+              pname = package.name;
+              inherit (package) version;
+              inherit src;
+              cargoLock.lockFile = (src + "/Cargo.lock");
+            };
+            default = config.packages.${package.name};
+          };
 
-            # Build tools
-            nativeBuildInputs = with pkgs; [
-              rust-toolchain
-              rust-analyzer
-              rustfmt
-            ];
+          devShells = {
+            ${package.name} = pkgs.mkShell {
+              inherit (package) name;
+              inputsFrom = [ config.packages.${package.name} ];
+              packages = with pkgs; [
+                rust-analyzer
+              ];
+            };
+            default = config.devShells.${package.name};
+          };
 
-            RUST_BACKTRACE = 1;
-            # CARGO_BUILD_TARGET = rust-target;
+          treefmt = {
+            projectRootFile = "flake.nix";
+            programs.nixpkgs-fmt.enable = true;
+            programs.rustfmt.enable = true;
           };
-          devShell = self.devShells."${system}".default;
-        });
-}
\ No newline at end of file
+        };
+    };
+}
diff --git a/src/main.rs b/src/main.rs
index 3033ece..9be3a25 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,10 +1,14 @@
+// #![allow(incomplete_features)]
+// #![feature(unsized_locals)]
 mod structs;
-use crate::structs::ElfHeader;
+use crate::structs::{ElfHeader, ElfSectionHeader};
+use std::io::Read;
 
 #[repr(C)]
 #[derive(Debug)]
 struct Elf {
     header: &'static ElfHeader,
+    sections: &'static [ElfSectionHeader],
 }
 
 impl Elf {
@@ -12,22 +16,51 @@ impl Elf {
         let header = unsafe { &*(bytes.as_ptr() as *const ElfHeader) };
         assert_eq!(&header.ident.magic, b"\x7fELF");
         
-        Elf {
-            header
+        let sections = unsafe {
+            std::slice::from_raw_parts(
+                bytes.as_ptr().add(header.shoff as usize) as *const ElfSectionHeader,
+                header.shnum as usize,
+            )
+        };
+
+        let strtab = &sections[header.shstrndx as usize];
+        let strtab_section = unsafe { bytes.as_ptr().add(strtab.offset as usize) };
+
+        // let names = unsafe {
+        //     std::slice::from_raw_parts(
+        //         strtab_section as *const u8,
+        //         strtab.size as usize,
+        //     )
+        // };
+        // dbg!(std::str::from_utf8(&names).unwrap());
+        for sec in sections {
+            println!("{:?}", unsafe { std::ffi::CStr::from_ptr(
+                strtab_section.add(sec.name as usize) as *const i8
+            )});
         }
+        // dbg!(sections[5].r#type as u32);
+        Elf { header, sections }
     }
 }
 
 // readelf behavior here
 impl std::fmt::Display for Elf {
     fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
-        formatter.write_str("ELF Header:\n");
+        formatter.write_str("ELF Header:\n")?;
         formatter.write_fmt(format_args!("{}", self.header))
     }
 }
 
 fn main() {
-    let data = include_bytes!("../elf");
-    let elf = Elf::new(&data[..]);
-    println!("{}", elf);
+    let args: Vec<String> = std::env::args().collect();
+
+    let buffer = {
+        let mut f = std::fs::File::open(&args[1]).expect("no file found");
+        let metadata = std::fs::metadata(&args[1]).expect("unable to read metadata");
+        let mut buffer = vec![0; metadata.len() as usize];
+        f.read(&mut buffer).expect("buffer overflow");
+        buffer
+    };
+    let elf = Elf::new(&buffer[..]);
+    // println!("{}", elf);
 }
diff --git a/src/structs.rs b/src/structs.rs
index 850a47c..69ec14e 100644
--- a/src/structs.rs
+++ b/src/structs.rs
@@ -1,47 +1,65 @@
+use bitflags::bitflags;
+
 #[repr(C, packed)]
 #[derive(Debug, Copy, Clone)]
 pub struct ElfIdent {
-	/// Magic number - 0x7F, then 'ELF' in ASCII
-	pub magic: [u8; 4],
-	
-	/// 1 = 32 bit, 2 = 64 bit
-	pub class: Class,
+    /// Magic number - 0x7F, then 'ELF' in ASCII
+    pub magic: [u8; 4],
+
+    /// 1 = 32 bit, 2 = 64 bit
+    pub class: Class,
 
-	// 1 = little endian, 2 = big endian
-	pub data: Endian,
+    // 1 = little endian, 2 = big endian
+    pub data: Endian,
 
-	/// ELF header version
-	pub version: u8,
+    /// ELF header version
+    pub version: u8,
 
-	/// OS ABI - usually 0 for System V
-	pub OSABI: OSABI,
+    /// OS ABI - usually 0 for System V
+    pub OSABI: OSABI,
 
-	// This field is used to distinguish among incompatible versions of an ABI.
-	pub ABIVersion: u8,
+    // This field is used to distinguish among incompatible versions of an ABI.
+    pub ABIVersion: u8,
 
-	/// Unused/padding
-	pub _unused: [u8; 7],
+    /// Unused/padding
+    pub _unused: [u8; 7],
 }
 
 impl std::fmt::Display for ElfIdent {
     fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
-        formatter.write_str("  Magic:   ");
-        
-        for b in unsafe {*(std::ptr::addr_of!(self.magic) as *const [u8; 16])} {
-            formatter.pad(&format!("{:02x?} ", b));
+        formatter.write_str("  Magic:   ")?;
+
+        for b in unsafe { *(std::ptr::addr_of!(self.magic) as *const [u8; 16]) } {
+            formatter.pad(&format!("{:02x?} ", b))?;
         }
 
-		formatter.write_str("\n");
-
-        formatter.write_fmt(format_args!("  Class:                             {:?}\n", self.class));
-        formatter.write_fmt(format_args!("  Data:                              {}\n", self.data));
-        formatter.write_fmt(format_args!("  Version:                           {} ({})\n", self.version, match self.version {
-			0 => "invalid",
-			1 => "current",
-			2_u8..=u8::MAX => todo!(), // need to cover all cases
-		}));
-        formatter.write_fmt(format_args!("  OS/ABI:                            {}\n", self.OSABI));
-        formatter.write_fmt(format_args!("  ABI Version:                       {}\n", self.ABIVersion))
+        formatter.write_str("\n")?;
+
+        formatter.write_fmt(format_args!(
+            "  Class:                             {:?}\n",
+            self.class
+        ))?;
+        formatter.write_fmt(format_args!(
+            "  Data:                              {}\n",
+            self.data
+        ))?;
+        formatter.write_fmt(format_args!(
+            "  Version:                           {} ({})\n",
+            self.version,
+            match self.version {
+                0 => "invalid",
+                1 => "current",
+                2_u8..=u8::MAX => todo!(), // need to cover all cases
+            }
+        ))?;
+        formatter.write_fmt(format_args!(
+            "  OS/ABI:                            {}\n",
+            self.OSABI
+        ))?;
+        formatter.write_fmt(format_args!(
+            "  ABI Version:                       {}\n",
+            self.ABIVersion
+        ))
     }
 }
 
@@ -51,153 +69,331 @@ impl std::fmt::Display for ElfIdent {
 #[repr(C)]
 #[derive(Debug)]
 pub struct ElfHeader {
-	pub ident: ElfIdent,
+    pub ident: ElfIdent,
+
+    /// 1 = relocatable, 2 = executable, 3 = shared, 4 = core
+    pub r#type: Type,
+
+    /// Instruction set - see table below
+    pub machine: Machine,
 
-	/// 1 = relocatable, 2 = executable, 3 = shared, 4 = core
-	pub r#type: Type,
-	
-	/// Instruction set - see table below
-	pub machine: Machine,
+    /// ELF Version
+    pub version: u32,
 
-	/// ELF Version
-	pub version: u32,
+    /// Program entry position (virtual)
+    pub entry: u64,
 
-	/// Program entry position (virtual)
-	pub entry: u64,
+    /// Program header table position (bytes into file)
+    pub phoff: u64,
 
-	/// Program header table position (bytes into file)
-	pub phoff: u64,
+    /// Section header table position (bytes into file)
+    pub shoff: u64,
 
-	/// Section header table position (bytes into file)
-	pub shoff: u64,
+    /// This member holds processor-specific flags associated with the file
+    /// Currently, no flags have been defined.
+    pub flags: u32,
 
-	/// This member holds processor-specific flags associated with the file
-	/// Currently, no flags have been defined.
-	pub flags: u32,
+    /// Header size
+    pub ehsize: u16,
 
-	/// Header size
-	pub ehsize: u16,
+    /// Size of an entry in the program header table
+    pub phentsize: u16,
 
-	/// Size of an entry in the program header table
-	pub phentsize: u16,
+    /// Number of entries in the program header table
+    pub phnum: u16,
 
-	/// Number of entries in the program header table
-	pub phnum: u16,
+    /// Size of an entry in the section header table
+    pub shentsize: u16,
 
-	/// Size of an entry in the section header table
-	pub shentsize: u16,
+    /// Number of entries in the section header table
+    pub shnum: u16,
 
-	/// Number of entries in the section header table
-	pub shnum: u16,
-	
-	/// Index in section header table with the section names
-	pub shstrndx: u16,
+    /// Index in section header table with the section names
+    pub shstrndx: u16,
 }
 
 impl std::fmt::Display for ElfHeader {
     fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
-		// yes, this is really what they do in readelf.c
-        formatter.write_fmt(format_args!("{}", self.ident));
-        formatter.write_fmt(format_args!("  Type:                              {}\n", self.r#type));
-        formatter.write_fmt(format_args!("  Machine:                           {}\n", self.machine));
-        formatter.write_fmt(format_args!("  Version:                           {:#02x?}\n", self.version));
-        formatter.write_fmt(format_args!("  Entry point address:               {:#x?}\n", self.entry));
-        formatter.write_fmt(format_args!("  Start of program headers:          {} (bytes into file)\n", self.phoff));
-        formatter.write_fmt(format_args!("  Start of section headers:          {} (bytes into file)\n", self.shoff));
-        formatter.write_fmt(format_args!("  Flags:                             {:#x?}\n", self.flags));
-        formatter.write_fmt(format_args!("  Size of this header:               {} (bytes)\n", self.ehsize));
-        formatter.write_fmt(format_args!("  Size of program headers:           {} (bytes)\n", self.phentsize));
-        formatter.write_fmt(format_args!("  Number of program headers:         {}\n", self.phnum));
-        formatter.write_fmt(format_args!("  Size of section headers:           {} (bytes)\n", self.shentsize));
-        formatter.write_fmt(format_args!("  Number of section headers:         {}\n", self.shnum));
-        formatter.write_fmt(format_args!("  Section header string table index: {}\n", self.shstrndx))
+        // yes, this is really what they do in readelf.c
+        formatter.write_fmt(format_args!("{}", self.ident))?;
+        formatter.write_fmt(format_args!(
+            "  Type:                              {}\n",
+            self.r#type
+        ))?;
+        formatter.write_fmt(format_args!(
+            "  Machine:                           {}\n",
+            self.machine
+        ))?;
+        formatter.write_fmt(format_args!(
+            "  Version:                           {:#02x?}\n",
+            self.version
+        ))?;
+        formatter.write_fmt(format_args!(
+            "  Entry point address:               {:#x?}\n",
+            self.entry
+        ))?;
+        formatter.write_fmt(format_args!(
+            "  Start of program headers:          {} (bytes into file)\n",
+            self.phoff
+        ))?;
+        formatter.write_fmt(format_args!(
+            "  Start of section headers:          {} (bytes into file)\n",
+            self.shoff
+        ))?;
+        formatter.write_fmt(format_args!(
+            "  Flags:                             {:#x?}\n",
+            self.flags
+        ))?;
+        formatter.write_fmt(format_args!(
+            "  Size of this header:               {} (bytes)\n",
+            self.ehsize
+        ))?;
+        formatter.write_fmt(format_args!(
+            "  Size of program headers:           {} (bytes)\n",
+            self.phentsize
+        ))?;
+        formatter.write_fmt(format_args!(
+            "  Number of program headers:         {}\n",
+            self.phnum
+        ))?;
+        formatter.write_fmt(format_args!(
+            "  Size of section headers:           {} (bytes)\n",
+            self.shentsize
+        ))?;
+        formatter.write_fmt(format_args!(
+            "  Number of section headers:         {}\n",
+            self.shnum
+        ))?;
+        formatter.write_fmt(format_args!(
+            "  Section header string table index: {}\n",
+            self.shstrndx
+        ))
     }
 }
 
 #[derive(Debug, Copy, Clone)]
 #[repr(u16)]
 pub enum Type {
-	None = 0,
-	Rel = 1,
-	Exec = 2,
-	Dyn = 3,
-	Core = 4,
+    None = 0,
+    Rel = 1,
+    Exec = 2,
+    Dyn = 3,
+    Core = 4,
 }
 
 impl std::fmt::Display for Type {
     fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
         match self {
-			Type::None => formatter.write_str("NONE (None)"),
-			Type::Rel => formatter.write_str("REL (Relocatable file)"),
-			Type::Exec => formatter.write_str("EXEC (Executable file)"),
-			Type::Dyn => formatter.write_str("DYN (Shared object file)"),
-			Type::Core => formatter.write_str("CORE (Core file)"),
-		}
+            Type::None => formatter.write_str("NONE (None)"),
+            Type::Rel => formatter.write_str("REL (Relocatable file)"),
+            Type::Exec => formatter.write_str("EXEC (Executable file)"),
+            Type::Dyn => formatter.write_str("DYN (Shared object file)"),
+            Type::Core => formatter.write_str("CORE (Core file)"),
+        }
     }
 }
 
 #[derive(Debug, Copy, Clone)]
 #[repr(u16)]
 pub enum Machine {
-	// there are many many many more, im just gonna do x86
-	// https://github.com/bminor/binutils-gdb/blob/master/binutils/readelf.c#L2746
-	None = 1,
-	X86_64 = 62,
+    // there are many many many more, im just gonna do x86
+    // https://github.com/bminor/binutils-gdb/blob/master/binutils/readelf.c#L2746
+    None = 1,
+    X86_64 = 62,
 }
 
 impl std::fmt::Display for Machine {
     fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
         match self {
-			Machine::None => formatter.write_str("None"),
-			Machine::X86_64 => formatter.write_str("Advanced Micro Devices X86-64"),
-		}
+            Machine::None => formatter.write_str("None"),
+            Machine::X86_64 => formatter.write_str("Advanced Micro Devices X86-64"),
+        }
     }
 }
 
-
 #[derive(Debug, Copy, Clone)]
 #[repr(u8)]
 pub enum Class {
-	ELF32 = 1,
-	ELF64 = 2,
+    ELF32 = 1,
+    ELF64 = 2,
 }
 
 #[derive(Debug, Copy, Clone)]
 #[repr(u8)]
 pub enum OSABI {
-	None = 0x00,
-	SystemV = 0x01,
-	// HPUX = 0x02,
-	// Solaris = 0x03,
-	// IRIX = 0x04,
-	// FreeBSD = 0x05,
-	// TRU64 = 0x06,
-	// ARM = 0x07,
-	Standalone = 0x08,
+    None = 0x00,
+    SystemV = 0x01,
+    // HPUX = 0x02,
+    // Solaris = 0x03,
+    // IRIX = 0x04,
+    // FreeBSD = 0x05,
+    // TRU64 = 0x06,
+    // ARM = 0x07,
+    Standalone = 0x08,
 }
 
 impl std::fmt::Display for OSABI {
     fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
         match self {
-			OSABI::None => formatter.write_str("UNIX - System V"),
-			OSABI::SystemV => formatter.write_str("UNIX - System V"),
-			OSABI::Standalone => formatter.write_str("Standalone"),
-		}
+            OSABI::None => formatter.write_str("UNIX - System V"),
+            OSABI::SystemV => formatter.write_str("UNIX - System V"),
+            OSABI::Standalone => formatter.write_str("Standalone"),
+        }
     }
 }
 
 #[derive(Debug, Copy, Clone)]
 #[repr(u8)]
 pub enum Endian {
-	Little = 1,
-	Big = 2,
+    Little = 1,
+    Big = 2,
 }
 
 impl std::fmt::Display for Endian {
     fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
         match self {
-			Endian::Little => formatter.write_str("2's complement, little endian"),
-			Endian::Big => formatter.write_str("1's complement, big endian"),
-		}
+            Endian::Little => formatter.write_str("2's complement, little endian"),
+            Endian::Big => formatter.write_str("1's complement, big endian"),
+        }
+    }
+}
+
+#[derive(Debug, Copy, Clone)]
+#[repr(C)]
+pub struct ElfSectionHeader {
+    /*  This member specifies the name of the section.  Its value
+    is an index into the section header string table section,
+    giving the location of a null-terminated string. */
+    pub name: u32,
+    /*  This member categorizes the section's contents and
+    semantics. */
+    pub r#type: ElfSectionType,
+
+    /*  Sections support one-bit flags that describe miscellaneous
+    attributes.  If a flag bit is set in sh_flags, the
+    attribute is "on" for the section.  Otherwise, the
+    attribute is "off" or does not apply.  Undefined
+    attributes are set to zero. */
+    pub flags: ElfSectionFlags,
+
+    /*  If this section appears in the memory image of a process,
+    this member holds the address at which the section's first
+    byte should reside.  Otherwise, the member contains zero. */
+    pub addr: u64,
+
+    /*  This member's value holds the byte offset from the
+    beginning of the file to the first byte in the section.
+    One section type, SHT_NOBITS, occupies no space in the
+    file, and its sh_offset member locates the conceptual
+    placement in the file. */
+    pub offset: u64,
+
+    /* 	This member holds the section's size in bytes.  Unless the
+    section type is SHT_NOBITS, the section occupies sh_size
+    bytes in the file.  A section of type SHT_NOBITS may have
+    a nonzero size, but it occupies no space in the file. */
+    pub size: u64,
+
+    /* 	This member holds a section header table index link, whose
+    interpretation depends on the section type. */
+    pub link: u32,
+
+    /* 	This member holds extra information, whose interpretation
+    depends on the section type. */
+    pub info: u32,
+
+    /* 	Some sections have address alignment constraints.  If a
+    section holds a doubleword, the system must ensure
+    doubleword alignment for the entire section.  That is, the
+    value of sh_addr must be congruent to zero, modulo the
+    value of sh_addralign.  Only zero and positive integral
+    powers of two are allowed.  The value 0 or 1 means that
+    the section has no alignment constraints. */
+    pub addralign: u64,
+
+    /*	Some sections hold a table of fixed-sized entries, such as
+    a symbol table.  For such a section, this member gives the
+    size in bytes for each entry.  This member contains zero
+    if the section does not hold a table of fixed-size
+    entries. */
+    pub entsize: u64,
+}
+
+#[derive(Debug, Copy, Clone)]
+#[repr(u32)]
+pub enum ElfSectionType {
+    /*  This value marks the section header as inactive.
+    It does not have an associated section.  Other
+    members of the section header have undefined
+    values. */
+    Null = 0,
+
+    /*  This section holds information defined by the
+    program, whose format and meaning are determined
+    solely by the program. */
+    ProgBits = 1,
+
+    /*  This section holds a symbol table.  Typically,
+    SHT_SYMTAB provides symbols for link editing,
+    though it may also be used for dynamic linking.  As
+    a complete symbol table, it may contain many
+    symbols unnecessary for dynamic linking.  An object
+    file can also contain a SHT_DYNSYM section. */
+    SymTab = 2,
+
+    /*  This section holds a string table.  An object file
+    may have multiple string table sections. */
+    StrTab = 3,
+
+    /*  This section holds relocation entries with explicit
+    addends, such as type Elf32_Rela for the 32-bit
+    class of object files.  An object may have multiple
+    relocation sections. */
+    Rela = 4,
+
+    /*  This section holds a symbol hash table.  An object
+    participating in dynamic linking must contain a
+    symbol hash table.  An object file may have only
+    one hash table. */
+    Hash = 5,
+
+    /*  This section holds information for dynamic linking.
+    An object file may have only one dynamic section. */
+    Dynamic = 6,
+
+    /* This section holds notes (ElfN_Nhdr). */
+    Note = 7,
+
+    /*  A section of this type occupies no space in the
+    file but otherwise resembles SHT_PROGBITS.
+    Although this section contains no bytes, the
+    sh_offset member contains the conceptual file
+    offset. */
+    NoBits = 8,
+
+    /*  This section holds relocation offsets without
+    explicit addends, such as type Elf32_Rel for the
+    32-bit class of object files.  An object file may
+    have multiple relocation sections. */
+    Rel = 9,
+
+    /*  This section is reserved but has unspecified
+    semantics. */
+    ShLib = 10,
+
+    /*  This section holds a minimal set of dynamic linking
+    symbols.  An object file can also contain a
+    SHT_SYMTAB section. */
+    DynSym = 11,
+
+    GnuHash = 0x6FFFFFF6,
+}
+
+bitflags! {
+	#[derive(Debug, Copy, Clone)]
+	pub struct ElfSectionFlags: u64 {
+        const WRITE = 0x1;
+        const ALLOC = 0x2;
+        const EXEC = 0x4;
     }
-}
\ No newline at end of file
+}