From c8a66c643afe2d0a2da55eac537b13a466c242c2 Mon Sep 17 00:00:00 2001 From: tzlil Date: Tue, 21 Mar 2023 12:56:39 +0200 Subject: reading section names --- .gitignore | 1 + Cargo.lock | 9 ++ Cargo.toml | 1 + flake.lock | 79 +++++------ flake.nix | 91 +++++------- src/main.rs | 47 ++++++- src/structs.rs | 426 +++++++++++++++++++++++++++++++++++++++++---------------- 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 @@ -2,6 +2,15 @@ # It is not intended for manual editing. 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 = §ions[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 = 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 +} -- cgit 1.4.1