macro_rules! elf_dyn {
($size:ty) => {
#[repr(C)]
#[derive(Copy, Clone, PartialEq, Default)]
#[cfg_attr(
feature = "alloc",
derive(scroll::Pread, scroll::Pwrite, scroll::SizeWith)
)]
pub struct Dyn {
pub d_tag: $size,
pub d_val: $size,
}
use plain;
unsafe impl plain::Plain for Dyn {}
};
}
pub const DT_NULL: u64 = 0;
pub const DT_NEEDED: u64 = 1;
pub const DT_PLTRELSZ: u64 = 2;
pub const DT_PLTGOT: u64 = 3;
pub const DT_HASH: u64 = 4;
pub const DT_STRTAB: u64 = 5;
pub const DT_SYMTAB: u64 = 6;
pub const DT_RELA: u64 = 7;
pub const DT_RELASZ: u64 = 8;
pub const DT_RELAENT: u64 = 9;
pub const DT_STRSZ: u64 = 10;
pub const DT_SYMENT: u64 = 11;
pub const DT_INIT: u64 = 12;
pub const DT_FINI: u64 = 13;
pub const DT_SONAME: u64 = 14;
pub const DT_RPATH: u64 = 15;
pub const DT_SYMBOLIC: u64 = 16;
pub const DT_REL: u64 = 17;
pub const DT_RELSZ: u64 = 18;
pub const DT_RELENT: u64 = 19;
pub const DT_PLTREL: u64 = 20;
pub const DT_DEBUG: u64 = 21;
pub const DT_TEXTREL: u64 = 22;
pub const DT_JMPREL: u64 = 23;
pub const DT_BIND_NOW: u64 = 24;
pub const DT_INIT_ARRAY: u64 = 25;
pub const DT_FINI_ARRAY: u64 = 26;
pub const DT_INIT_ARRAYSZ: u64 = 27;
pub const DT_FINI_ARRAYSZ: u64 = 28;
pub const DT_RUNPATH: u64 = 29;
pub const DT_FLAGS: u64 = 30;
pub const DT_ENCODING: u64 = 32;
pub const DT_PREINIT_ARRAY: u64 = 32;
pub const DT_PREINIT_ARRAYSZ: u64 = 33;
pub const DT_NUM: u64 = 34;
pub const DT_LOOS: u64 = 0x6000_000d;
pub const DT_HIOS: u64 = 0x6fff_f000;
pub const DT_LOPROC: u64 = 0x7000_0000;
pub const DT_HIPROC: u64 = 0x7fff_ffff;
pub const DT_ADDRRNGLO: u64 = 0x6fff_fe00;
pub const DT_GNU_HASH: u64 = 0x6fff_fef5;
pub const DT_TLSDESC_PLT: u64 = 0x6fff_fef6;
pub const DT_TLSDESC_GOT: u64 = 0x6fff_fef7;
pub const DT_GNU_CONFLICT: u64 = 0x6fff_fef8;
pub const DT_GNU_LIBLIST: u64 = 0x6fff_fef9;
pub const DT_CONFIG: u64 = 0x6fff_fefa;
pub const DT_DEPAUDIT: u64 = 0x6fff_fefb;
pub const DT_AUDIT: u64 = 0x6fff_fefc;
pub const DT_PLTPAD: u64 = 0x6fff_fefd;
pub const DT_MOVETAB: u64 = 0x6fff_fefe;
pub const DT_SYMINFO: u64 = 0x6fff_feff;
pub const DT_ADDRRNGHI: u64 = 0x6fff_feff;
pub const DT_ADDRNUM: u64 = 11;
pub const DT_VERSYM: u64 = 0x6fff_fff0;
pub const DT_RELACOUNT: u64 = 0x6fff_fff9;
pub const DT_RELCOUNT: u64 = 0x6fff_fffa;
pub const DT_FLAGS_1: u64 = 0x6fff_fffb;
pub const DT_VERDEF: u64 = 0x6fff_fffc;
pub const DT_VERDEFNUM: u64 = 0x6fff_fffd;
pub const DT_VERNEED: u64 = 0x6fff_fffe;
pub const DT_VERNEEDNUM: u64 = 0x6fff_ffff;
#[inline]
pub fn tag_to_str(tag: u64) -> &'static str {
match tag {
DT_NULL => "DT_NULL",
DT_NEEDED => "DT_NEEDED",
DT_PLTRELSZ => "DT_PLTRELSZ",
DT_PLTGOT => "DT_PLTGOT",
DT_HASH => "DT_HASH",
DT_STRTAB => "DT_STRTAB",
DT_SYMTAB => "DT_SYMTAB",
DT_RELA => "DT_RELA",
DT_RELASZ => "DT_RELASZ",
DT_RELAENT => "DT_RELAENT",
DT_STRSZ => "DT_STRSZ",
DT_SYMENT => "DT_SYMENT",
DT_INIT => "DT_INIT",
DT_FINI => "DT_FINI",
DT_SONAME => "DT_SONAME",
DT_RPATH => "DT_RPATH",
DT_SYMBOLIC => "DT_SYMBOLIC",
DT_REL => "DT_REL",
DT_RELSZ => "DT_RELSZ",
DT_RELENT => "DT_RELENT",
DT_PLTREL => "DT_PLTREL",
DT_DEBUG => "DT_DEBUG",
DT_TEXTREL => "DT_TEXTREL",
DT_JMPREL => "DT_JMPREL",
DT_BIND_NOW => "DT_BIND_NOW",
DT_INIT_ARRAY => "DT_INIT_ARRAY",
DT_FINI_ARRAY => "DT_FINI_ARRAY",
DT_INIT_ARRAYSZ => "DT_INIT_ARRAYSZ",
DT_FINI_ARRAYSZ => "DT_FINI_ARRAYSZ",
DT_RUNPATH => "DT_RUNPATH",
DT_FLAGS => "DT_FLAGS",
DT_PREINIT_ARRAY => "DT_PREINIT_ARRAY",
DT_PREINIT_ARRAYSZ => "DT_PREINIT_ARRAYSZ",
DT_NUM => "DT_NUM",
DT_LOOS => "DT_LOOS",
DT_HIOS => "DT_HIOS",
DT_LOPROC => "DT_LOPROC",
DT_HIPROC => "DT_HIPROC",
DT_VERSYM => "DT_VERSYM",
DT_RELACOUNT => "DT_RELACOUNT",
DT_RELCOUNT => "DT_RELCOUNT",
DT_GNU_HASH => "DT_GNU_HASH",
DT_VERDEF => "DT_VERDEF",
DT_VERDEFNUM => "DT_VERDEFNUM",
DT_VERNEED => "DT_VERNEED",
DT_VERNEEDNUM => "DT_VERNEEDNUM",
DT_FLAGS_1 => "DT_FLAGS_1",
_ => "UNKNOWN_TAG",
}
}
pub const DF_ORIGIN: u64 = 0x0000_0001;
pub const DF_SYMBOLIC: u64 = 0x0000_0002;
pub const DF_TEXTREL: u64 = 0x0000_0004;
pub const DF_BIND_NOW: u64 = 0x0000_0008;
pub const DF_STATIC_TLS: u64 = 0x0000_0010;
pub fn df_tag_to_str(tag: u64) -> &'static str {
match tag {
DF_ORIGIN => "DF_ORIGIN",
DF_SYMBOLIC => "DF_SYMBOLIC",
DF_TEXTREL => "DF_TEXTREL",
DF_BIND_NOW => "DF_BIND_NOW",
DF_STATIC_TLS => "DF_STATIC_TLS",
_ => "UNKNOWN_TAG",
}
}
pub const DF_1_NOW: u64 = 0x0000_0001;
pub const DF_1_GLOBAL: u64 = 0x0000_0002;
pub const DF_1_GROUP: u64 = 0x0000_0004;
pub const DF_1_NODELETE: u64 = 0x0000_0008;
pub const DF_1_LOADFLTR: u64 = 0x0000_0010;
pub const DF_1_INITFIRST: u64 = 0x0000_0020;
pub const DF_1_NOOPEN: u64 = 0x0000_0040;
pub const DF_1_ORIGIN: u64 = 0x0000_0080;
pub const DF_1_DIRECT: u64 = 0x0000_0100;
pub const DF_1_TRANS: u64 = 0x0000_0200;
pub const DF_1_INTERPOSE: u64 = 0x0000_0400;
pub const DF_1_NODEFLIB: u64 = 0x0000_0800;
pub const DF_1_NODUMP: u64 = 0x0000_1000;
pub const DF_1_CONFALT: u64 = 0x0000_2000;
pub const DF_1_ENDFILTEE: u64 = 0x0000_4000;
pub const DF_1_DISPRELDNE: u64 = 0x0000_8000;
pub const DF_1_DISPRELPND: u64 = 0x0001_0000;
pub const DF_1_NODIRECT: u64 = 0x0002_0000;
pub const DF_1_IGNMULDEF: u64 = 0x0004_0000;
pub const DF_1_NOKSYMS: u64 = 0x0008_0000;
pub const DF_1_NOHDR: u64 = 0x0010_0000;
pub const DF_1_EDITED: u64 = 0x0020_0000;
pub const DF_1_NORELOC: u64 = 0x0040_0000;
pub const DF_1_SYMINTPOSE: u64 = 0x0080_0000;
pub const DF_1_GLOBAUDIT: u64 = 0x0100_0000;
pub const DF_1_SINGLETON: u64 = 0x0200_0000;
pub const DF_1_PIE: u64 = 0x0800_0000;
pub fn df_1_tag_to_str(tag: u64) -> &'static str {
match tag {
DF_1_NOW => "DF_1_NOW",
DF_1_GLOBAL => "DF_1_GLOBAL",
DF_1_GROUP => "DF_1_GROUP",
DF_1_NODELETE => "DF_1_NODELETE",
DF_1_LOADFLTR => "DF_1_LOADFLTR",
DF_1_INITFIRST => "DF_1_INITFIRST",
DF_1_NOOPEN => "DF_1_NOOPEN",
DF_1_ORIGIN => "DF_1_ORIGIN",
DF_1_DIRECT => "DF_1_DIRECT",
DF_1_TRANS => "DF_1_TRANS",
DF_1_INTERPOSE => "DF_1_INTERPOSE",
DF_1_NODEFLIB => "DF_1_NODEFLIB",
DF_1_NODUMP => "DF_1_NODUMP",
DF_1_CONFALT => "DF_1_CONFALT",
DF_1_ENDFILTEE => "DF_1_ENDFILTEE",
DF_1_DISPRELDNE => "DF_1_DISPRELDNE",
DF_1_DISPRELPND => "DF_1_DISPRELPND",
DF_1_NODIRECT => "DF_1_NODIRECT",
DF_1_IGNMULDEF => "DF_1_IGNMULDEF",
DF_1_NOKSYMS => "DF_1_NOKSYMS",
DF_1_NOHDR => "DF_1_NOHDR",
DF_1_EDITED => "DF_1_EDITED",
DF_1_NORELOC => "DF_1_NORELOC",
DF_1_SYMINTPOSE => "DF_1_SYMINTPOSE",
DF_1_GLOBAUDIT => "DF_1_GLOBAUDIT",
DF_1_SINGLETON => "DF_1_SINGLETON",
DF_1_PIE => "DF_1_PIE",
_ => "UNKNOWN_TAG",
}
}
if_alloc! {
use core::fmt;
use scroll::ctx;
use core::result;
use crate::container::{Ctx, Container};
use crate::strtab::Strtab;
use alloc::vec::Vec;
#[derive(Default, PartialEq, Clone)]
pub struct Dyn {
pub d_tag: u64,
pub d_val: u64,
}
impl Dyn {
#[inline]
pub fn size(container: Container) -> usize {
use scroll::ctx::SizeWith;
Self::size_with(&Ctx::from(container))
}
}
impl fmt::Debug for Dyn {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Dyn")
.field("d_tag", &tag_to_str(self.d_tag))
.field("d_val", &format_args!("0x{:x}", self.d_val))
.finish()
}
}
impl ctx::SizeWith<Ctx> for Dyn {
fn size_with(&Ctx { container, .. }: &Ctx) -> usize {
match container {
Container::Little => {
dyn32::SIZEOF_DYN
},
Container::Big => {
dyn64::SIZEOF_DYN
},
}
}
}
impl<'a> ctx::TryFromCtx<'a, Ctx> for Dyn {
type Error = crate::error::Error;
fn try_from_ctx(bytes: &'a [u8], Ctx { container, le}: Ctx) -> result::Result<(Self, usize), Self::Error> {
use scroll::Pread;
let dynamic = match container {
Container::Little => {
(bytes.pread_with::<dyn32::Dyn>(0, le)?.into(), dyn32::SIZEOF_DYN)
},
Container::Big => {
(bytes.pread_with::<dyn64::Dyn>(0, le)?.into(), dyn64::SIZEOF_DYN)
}
};
Ok(dynamic)
}
}
impl ctx::TryIntoCtx<Ctx> for Dyn {
type Error = crate::error::Error;
fn try_into_ctx(self, bytes: &mut [u8], Ctx { container, le}: Ctx) -> result::Result<usize, Self::Error> {
use scroll::Pwrite;
match container {
Container::Little => {
let dynamic: dyn32::Dyn = self.into();
Ok(bytes.pwrite_with(dynamic, 0, le)?)
},
Container::Big => {
let dynamic: dyn64::Dyn = self.into();
Ok(bytes.pwrite_with(dynamic, 0, le)?)
}
}
}
}
#[derive(Debug)]
pub struct Dynamic {
pub dyns: Vec<Dyn>,
pub info: DynamicInfo,
count: usize,
}
impl Dynamic {
#[cfg(feature = "endian_fd")]
pub fn parse(bytes: &[u8], phdrs: &[crate::elf::program_header::ProgramHeader], ctx: Ctx) -> crate::error::Result<Option<Self>> {
use scroll::ctx::SizeWith;
use scroll::Pread;
use crate::elf::program_header;
for phdr in phdrs {
if phdr.p_type == program_header::PT_DYNAMIC {
let offset = phdr.p_offset as usize;
let filesz = phdr.p_filesz as usize;
let bytes = if filesz > 0 {
bytes
.pread_with::<&[u8]>(offset, filesz)
.map_err(|_| crate::error::Error::Malformed(format!("Invalid PT_DYNAMIC size (offset {:#x}, filesz {:#x})",
offset, filesz)))?
} else {
&[]
};
let size = Dyn::size_with(&ctx);
let count = filesz / size;
let mut dyns = Vec::with_capacity(count);
let mut offset = 0;
for _ in 0..count {
let dynamic = bytes.gread_with::<Dyn>(&mut offset, ctx)?;
let tag = dynamic.d_tag;
dyns.push(dynamic);
if tag == DT_NULL { break }
}
let mut info = DynamicInfo::default();
for dynamic in &dyns {
info.update(phdrs, dynamic);
}
let count = dyns.len();
return Ok(Some(Dynamic { dyns: dyns, info: info, count: count }));
}
}
Ok(None)
}
pub fn get_libraries<'a>(&self, strtab: &Strtab<'a>) -> Vec<&'a str> {
use log::warn;
let count = self.info.needed_count;
let mut needed = Vec::with_capacity(count);
for dynamic in &self.dyns {
if dynamic.d_tag as u64 == DT_NEEDED {
if let Some(Ok(lib)) = strtab.get(dynamic.d_val as usize) {
needed.push(lib)
} else {
warn!("Invalid DT_NEEDED {}", dynamic.d_val)
}
}
}
needed
}
}
}
macro_rules! elf_dyn_std_impl {
($size:ident, $phdr:ty) => {
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn size_of() {
assert_eq!(::std::mem::size_of::<Dyn>(), SIZEOF_DYN);
}
}
if_alloc! {
use core::fmt;
use core::slice;
use alloc::vec::Vec;
use crate::elf::program_header::{PT_DYNAMIC};
use crate::strtab::Strtab;
use crate::elf::dynamic::Dyn as ElfDyn;
if_std! {
use std::fs::File;
use std::io::{Read, Seek};
use std::io::SeekFrom::Start;
use crate::error::Result;
}
impl From<ElfDyn> for Dyn {
fn from(dynamic: ElfDyn) -> Self {
Dyn {
d_tag: dynamic.d_tag as $size,
d_val: dynamic.d_val as $size,
}
}
}
impl From<Dyn> for ElfDyn {
fn from(dynamic: Dyn) -> Self {
ElfDyn {
d_tag: u64::from(dynamic.d_tag),
d_val: u64::from(dynamic.d_val),
}
}
}
impl fmt::Debug for Dyn {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Dyn")
.field("d_tag", &tag_to_str(u64::from(self.d_tag)))
.field("d_val", &format_args!("0x{:x}", self.d_val))
.finish()
}
}
#[cfg(feature = "std")]
pub fn from_fd(mut fd: &File, phdrs: &[$phdr]) -> Result<Option<Vec<Dyn>>> {
for phdr in phdrs {
if phdr.p_type == PT_DYNAMIC {
let filesz = phdr.p_filesz as usize;
let dync = filesz / SIZEOF_DYN;
let mut dyns = vec![Dyn::default(); dync];
fd.seek(Start(u64::from(phdr.p_offset)))?;
unsafe {
fd.read_exact(plain::as_mut_bytes(&mut *dyns))?;
}
dyns.dedup();
return Ok(Some(dyns));
}
}
Ok(None)
}
pub unsafe fn from_raw<'a>(bias: usize, vaddr: usize) -> &'a [Dyn] {
let dynp = vaddr.wrapping_add(bias) as *const Dyn;
let mut idx = 0;
while u64::from((*dynp.offset(idx)).d_tag) != DT_NULL {
idx += 1;
}
slice::from_raw_parts(dynp, idx as usize)
}
pub unsafe fn from_phdrs(bias: usize, phdrs: &[$phdr]) -> Option<&[Dyn]> {
for phdr in phdrs {
if phdr.p_type as u32 == PT_DYNAMIC {
return Some(from_raw(bias, phdr.p_vaddr as usize));
}
}
None
}
pub unsafe fn get_needed<'a>(dyns: &[Dyn], strtab: *const Strtab<'a>, count: usize) -> Vec<&'a str> {
let mut needed = Vec::with_capacity(count);
for dynamic in dyns {
if u64::from(dynamic.d_tag) == DT_NEEDED {
let lib = &(*strtab)[dynamic.d_val as usize];
needed.push(lib);
}
}
needed
}
}
};
}
macro_rules! elf_dynamic_info_std_impl {
($size:ident, $phdr:ty) => {
fn vm_to_offset(phdrs: &[$phdr], address: $size) -> Option<$size> {
for ph in phdrs {
if address >= ph.p_vaddr {
let offset = address - ph.p_vaddr;
if offset < ph.p_memsz {
return ph.p_offset.checked_add(offset);
}
}
}
None
}
#[derive(Default, PartialEq)]
pub struct DynamicInfo {
pub rela: usize,
pub relasz: usize,
pub relaent: $size,
pub relacount: usize,
pub rel: usize,
pub relsz: usize,
pub relent: $size,
pub relcount: usize,
pub gnu_hash: Option<$size>,
pub hash: Option<$size>,
pub strtab: usize,
pub strsz: usize,
pub symtab: usize,
pub syment: usize,
pub pltgot: Option<$size>,
pub pltrelsz: usize,
pub pltrel: $size,
pub jmprel: usize,
pub verneed: $size,
pub verneednum: $size,
pub versym: $size,
pub init: $size,
pub fini: $size,
pub init_array: $size,
pub init_arraysz: usize,
pub fini_array: $size,
pub fini_arraysz: usize,
pub needed_count: usize,
pub flags: $size,
pub flags_1: $size,
pub soname: usize,
pub textrel: bool,
}
impl DynamicInfo {
#[inline]
pub fn update(&mut self, phdrs: &[$phdr], dynamic: &Dyn) {
match u64::from(dynamic.d_tag) {
DT_RELA => self.rela = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0) as usize,
DT_RELASZ => self.relasz = dynamic.d_val as usize,
DT_RELAENT => self.relaent = dynamic.d_val as _,
DT_RELACOUNT => self.relacount = dynamic.d_val as usize,
DT_REL => self.rel = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0) as usize,
DT_RELSZ => self.relsz = dynamic.d_val as usize,
DT_RELENT => self.relent = dynamic.d_val as _,
DT_RELCOUNT => self.relcount = dynamic.d_val as usize,
DT_GNU_HASH => self.gnu_hash = vm_to_offset(phdrs, dynamic.d_val),
DT_HASH => self.hash = vm_to_offset(phdrs, dynamic.d_val),
DT_STRTAB => {
self.strtab = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0) as usize
}
DT_STRSZ => self.strsz = dynamic.d_val as usize,
DT_SYMTAB => {
self.symtab = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0) as usize
}
DT_SYMENT => self.syment = dynamic.d_val as usize,
DT_PLTGOT => self.pltgot = vm_to_offset(phdrs, dynamic.d_val),
DT_PLTRELSZ => self.pltrelsz = dynamic.d_val as usize,
DT_PLTREL => self.pltrel = dynamic.d_val as _,
DT_JMPREL => {
self.jmprel = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0) as usize
}
DT_VERNEED => self.verneed = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0),
DT_VERNEEDNUM => self.verneednum = dynamic.d_val as _,
DT_VERSYM => self.versym = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0),
DT_INIT => self.init = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0),
DT_FINI => self.fini = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0),
DT_INIT_ARRAY => {
self.init_array = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0)
}
DT_INIT_ARRAYSZ => self.init_arraysz = dynamic.d_val as _,
DT_FINI_ARRAY => {
self.fini_array = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0)
}
DT_FINI_ARRAYSZ => self.fini_arraysz = dynamic.d_val as _,
DT_NEEDED => self.needed_count += 1,
DT_FLAGS => self.flags = dynamic.d_val as _,
DT_FLAGS_1 => self.flags_1 = dynamic.d_val as _,
DT_SONAME => self.soname = dynamic.d_val as _,
DT_TEXTREL => self.textrel = true,
_ => (),
}
}
pub fn new(dynamic: &[Dyn], phdrs: &[$phdr]) -> DynamicInfo {
let mut info = DynamicInfo::default();
for dyna in dynamic {
info.update(phdrs, &dyna);
}
info
}
}
if_alloc! {
impl fmt::Debug for DynamicInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let gnu_hash = self.gnu_hash.unwrap_or(0);
let hash = self.hash.unwrap_or(0);
let pltgot = self.pltgot.unwrap_or(0);
let flags: Vec<&'static str> = [DF_ORIGIN, DF_SYMBOLIC, DF_TEXTREL, DF_BIND_NOW, DF_STATIC_TLS,][..]
.iter()
.filter(|f| (self.flags as u64 & *f) != 0)
.map(|f| df_tag_to_str(*f))
.collect();
let flags_1: Vec<&'static str> = [
DF_1_NOW,
DF_1_GLOBAL,
DF_1_GROUP,
DF_1_NODELETE,
DF_1_LOADFLTR,
DF_1_INITFIRST,
DF_1_NOOPEN,
DF_1_ORIGIN,
DF_1_DIRECT,
DF_1_TRANS,
DF_1_INTERPOSE,
DF_1_NODEFLIB,
DF_1_NODUMP,
DF_1_CONFALT,
DF_1_ENDFILTEE,
DF_1_DISPRELDNE,
DF_1_DISPRELPND,
DF_1_NODIRECT,
DF_1_IGNMULDEF,
DF_1_NOKSYMS,
DF_1_NOHDR,
DF_1_EDITED,
DF_1_NORELOC,
DF_1_SYMINTPOSE,
DF_1_GLOBAUDIT,
DF_1_SINGLETON,
DF_1_PIE,
][..]
.iter()
.filter(|f| (self.flags_1 as u64 & *f) != 0)
.map(|f| df_1_tag_to_str(*f))
.collect();
f.debug_struct("DynamicInfo")
.field("rela", &format_args!("0x{:x}", self.rela))
.field("relasz", &self.relasz)
.field("relaent", &self.relaent)
.field("relacount", &self.relacount)
.field("gnu_hash", &format_args!("0x{:x}", gnu_hash))
.field("hash", &format_args!("0x{:x}", hash))
.field("strtab", &format_args!("0x{:x}", self.strtab))
.field("strsz", &self.strsz)
.field("symtab", &format_args!("0x{:x}", self.symtab))
.field("syment", &self.syment)
.field("pltgot", &format_args!("0x{:x}", pltgot))
.field("pltrelsz", &self.pltrelsz)
.field("pltrel", &self.pltrel)
.field("jmprel", &format_args!("0x{:x}", self.jmprel))
.field("verneed", &format_args!("0x{:x}", self.verneed))
.field("verneednum", &self.verneednum)
.field("versym", &format_args!("0x{:x}", self.versym))
.field("init", &format_args!("0x{:x}", self.init))
.field("fini", &format_args!("0x{:x}", self.fini))
.field("init_array", &format_args!("{:#x}", self.init_array))
.field("init_arraysz", &self.init_arraysz)
.field("needed_count", &self.needed_count)
.field("flags", &format_args!("{:#0width$x} {:?}", self.flags, flags, width = core::mem::size_of_val(&self.flags)))
.field("flags_1", &format_args!("{:#0width$x} {:?}", self.flags_1, flags_1, width = core::mem::size_of_val(&self.flags_1)))
.field("soname", &self.soname)
.field("textrel", &self.textrel)
.finish()
}
}
}
};
}
if_alloc! {
elf_dynamic_info_std_impl!(u64, crate::elf::program_header::ProgramHeader);
}
pub mod dyn32 {
pub use crate::elf::dynamic::*;
elf_dyn!(u32);
pub const SIZEOF_DYN: usize = 8;
elf_dyn_std_impl!(u32, crate::elf32::program_header::ProgramHeader);
elf_dynamic_info_std_impl!(
u32,
crate::elf::program_header::program_header32::ProgramHeader
);
}
pub mod dyn64 {
pub use crate::elf::dynamic::*;
elf_dyn!(u64);
pub const SIZEOF_DYN: usize = 16;
elf_dyn_std_impl!(u64, crate::elf64::program_header::ProgramHeader);
elf_dynamic_info_std_impl!(
u64,
crate::elf::program_header::program_header64::ProgramHeader
);
}