1macro_rules! elf_dyn {
2 ($size:ty) => {
3 #[repr(C)]
7 #[derive(Copy, Clone, PartialEq, Default)]
8 #[cfg_attr(
9 feature = "alloc",
10 derive(scroll::Pread, scroll::Pwrite, scroll::SizeWith)
11 )]
12 pub struct Dyn {
14 pub d_tag: $size,
16 pub d_val: $size,
18 }
19
20 use plain;
21 unsafe impl plain::Plain for Dyn {}
22 };
23}
24
25pub const DT_NULL: u64 = 0;
33pub const DT_NEEDED: u64 = 1;
35pub const DT_PLTRELSZ: u64 = 2;
37pub const DT_PLTGOT: u64 = 3;
39pub const DT_HASH: u64 = 4;
41pub const DT_STRTAB: u64 = 5;
43pub const DT_SYMTAB: u64 = 6;
45pub const DT_RELA: u64 = 7;
47pub const DT_RELASZ: u64 = 8;
49pub const DT_RELAENT: u64 = 9;
51pub const DT_STRSZ: u64 = 10;
53pub const DT_SYMENT: u64 = 11;
55pub const DT_INIT: u64 = 12;
57pub const DT_FINI: u64 = 13;
59pub const DT_SONAME: u64 = 14;
61pub const DT_RPATH: u64 = 15;
63pub const DT_SYMBOLIC: u64 = 16;
65pub const DT_REL: u64 = 17;
67pub const DT_RELSZ: u64 = 18;
69pub const DT_RELENT: u64 = 19;
71pub const DT_PLTREL: u64 = 20;
73pub const DT_DEBUG: u64 = 21;
75pub const DT_TEXTREL: u64 = 22;
77pub const DT_JMPREL: u64 = 23;
79pub const DT_BIND_NOW: u64 = 24;
81pub const DT_INIT_ARRAY: u64 = 25;
83pub const DT_FINI_ARRAY: u64 = 26;
85pub const DT_INIT_ARRAYSZ: u64 = 27;
87pub const DT_FINI_ARRAYSZ: u64 = 28;
89pub const DT_RUNPATH: u64 = 29;
91pub const DT_FLAGS: u64 = 30;
93pub const DT_ENCODING: u64 = 32;
95pub const DT_PREINIT_ARRAY: u64 = 32;
97pub const DT_PREINIT_ARRAYSZ: u64 = 33;
99pub const DT_NUM: u64 = 34;
101pub const DT_LOOS: u64 = 0x6000_000d;
103pub const DT_HIOS: u64 = 0x6fff_f000;
105pub const DT_LOPROC: u64 = 0x7000_0000;
107pub const DT_HIPROC: u64 = 0x7fff_ffff;
109pub const DT_ADDRRNGLO: u64 = 0x6fff_fe00;
118pub const DT_GNU_HASH: u64 = 0x6fff_fef5;
120pub const DT_TLSDESC_PLT: u64 = 0x6fff_fef6;
122pub const DT_TLSDESC_GOT: u64 = 0x6fff_fef7;
124pub const DT_GNU_CONFLICT: u64 = 0x6fff_fef8;
126pub const DT_GNU_LIBLIST: u64 = 0x6fff_fef9;
128pub const DT_CONFIG: u64 = 0x6fff_fefa;
130pub const DT_DEPAUDIT: u64 = 0x6fff_fefb;
132pub const DT_AUDIT: u64 = 0x6fff_fefc;
134pub const DT_PLTPAD: u64 = 0x6fff_fefd;
136pub const DT_MOVETAB: u64 = 0x6fff_fefe;
138pub const DT_SYMINFO: u64 = 0x6fff_feff;
140pub const DT_ADDRRNGHI: u64 = 0x6fff_feff;
142
143pub const DT_ADDRNUM: u64 = 11;
145
146pub const DT_VERSYM: u64 = 0x6fff_fff0;
148pub const DT_RELACOUNT: u64 = 0x6fff_fff9;
149pub const DT_RELCOUNT: u64 = 0x6fff_fffa;
150pub const DT_FLAGS_1: u64 = 0x6fff_fffb;
152pub const DT_VERDEF: u64 = 0x6fff_fffc;
154pub const DT_VERDEFNUM: u64 = 0x6fff_fffd;
156pub const DT_VERNEED: u64 = 0x6fff_fffe;
158pub const DT_VERNEEDNUM: u64 = 0x6fff_ffff;
160
161#[inline]
163pub fn tag_to_str(tag: u64) -> &'static str {
164 match tag {
165 DT_NULL => "DT_NULL",
166 DT_NEEDED => "DT_NEEDED",
167 DT_PLTRELSZ => "DT_PLTRELSZ",
168 DT_PLTGOT => "DT_PLTGOT",
169 DT_HASH => "DT_HASH",
170 DT_STRTAB => "DT_STRTAB",
171 DT_SYMTAB => "DT_SYMTAB",
172 DT_RELA => "DT_RELA",
173 DT_RELASZ => "DT_RELASZ",
174 DT_RELAENT => "DT_RELAENT",
175 DT_STRSZ => "DT_STRSZ",
176 DT_SYMENT => "DT_SYMENT",
177 DT_INIT => "DT_INIT",
178 DT_FINI => "DT_FINI",
179 DT_SONAME => "DT_SONAME",
180 DT_RPATH => "DT_RPATH",
181 DT_SYMBOLIC => "DT_SYMBOLIC",
182 DT_REL => "DT_REL",
183 DT_RELSZ => "DT_RELSZ",
184 DT_RELENT => "DT_RELENT",
185 DT_PLTREL => "DT_PLTREL",
186 DT_DEBUG => "DT_DEBUG",
187 DT_TEXTREL => "DT_TEXTREL",
188 DT_JMPREL => "DT_JMPREL",
189 DT_BIND_NOW => "DT_BIND_NOW",
190 DT_INIT_ARRAY => "DT_INIT_ARRAY",
191 DT_FINI_ARRAY => "DT_FINI_ARRAY",
192 DT_INIT_ARRAYSZ => "DT_INIT_ARRAYSZ",
193 DT_FINI_ARRAYSZ => "DT_FINI_ARRAYSZ",
194 DT_RUNPATH => "DT_RUNPATH",
195 DT_FLAGS => "DT_FLAGS",
196 DT_PREINIT_ARRAY => "DT_PREINIT_ARRAY",
197 DT_PREINIT_ARRAYSZ => "DT_PREINIT_ARRAYSZ",
198 DT_NUM => "DT_NUM",
199 DT_LOOS => "DT_LOOS",
200 DT_HIOS => "DT_HIOS",
201 DT_LOPROC => "DT_LOPROC",
202 DT_HIPROC => "DT_HIPROC",
203 DT_VERSYM => "DT_VERSYM",
204 DT_RELACOUNT => "DT_RELACOUNT",
205 DT_RELCOUNT => "DT_RELCOUNT",
206 DT_GNU_HASH => "DT_GNU_HASH",
207 DT_VERDEF => "DT_VERDEF",
208 DT_VERDEFNUM => "DT_VERDEFNUM",
209 DT_VERNEED => "DT_VERNEED",
210 DT_VERNEEDNUM => "DT_VERNEEDNUM",
211 DT_FLAGS_1 => "DT_FLAGS_1",
212 _ => "UNKNOWN_TAG",
213 }
214}
215
216pub const DF_ORIGIN: u64 = 0x0000_0001;
219pub const DF_SYMBOLIC: u64 = 0x0000_0002;
221pub const DF_TEXTREL: u64 = 0x0000_0004;
223pub const DF_BIND_NOW: u64 = 0x0000_0008;
225pub const DF_STATIC_TLS: u64 = 0x0000_0010;
227
228pub fn df_tag_to_str(tag: u64) -> &'static str {
229 match tag {
230 DF_ORIGIN => "DF_ORIGIN",
231 DF_SYMBOLIC => "DF_SYMBOLIC",
232 DF_TEXTREL => "DF_TEXTREL",
233 DF_BIND_NOW => "DF_BIND_NOW",
234 DF_STATIC_TLS => "DF_STATIC_TLS",
235 _ => "UNKNOWN_TAG",
236 }
237}
238
239pub const DF_1_NOW: u64 = 0x0000_0001;
244pub const DF_1_GLOBAL: u64 = 0x0000_0002;
246pub const DF_1_GROUP: u64 = 0x0000_0004;
248pub const DF_1_NODELETE: u64 = 0x0000_0008;
250pub const DF_1_LOADFLTR: u64 = 0x0000_0010;
252pub const DF_1_INITFIRST: u64 = 0x0000_0020;
254pub const DF_1_NOOPEN: u64 = 0x0000_0040;
256pub const DF_1_ORIGIN: u64 = 0x0000_0080;
258pub const DF_1_DIRECT: u64 = 0x0000_0100;
260pub const DF_1_TRANS: u64 = 0x0000_0200;
261pub const DF_1_INTERPOSE: u64 = 0x0000_0400;
263pub const DF_1_NODEFLIB: u64 = 0x0000_0800;
265pub const DF_1_NODUMP: u64 = 0x0000_1000;
267pub const DF_1_CONFALT: u64 = 0x0000_2000;
269pub const DF_1_ENDFILTEE: u64 = 0x0000_4000;
271pub const DF_1_DISPRELDNE: u64 = 0x0000_8000;
273pub const DF_1_DISPRELPND: u64 = 0x0001_0000;
275pub const DF_1_NODIRECT: u64 = 0x0002_0000;
277pub const DF_1_IGNMULDEF: u64 = 0x0004_0000;
278pub const DF_1_NOKSYMS: u64 = 0x0008_0000;
279pub const DF_1_NOHDR: u64 = 0x0010_0000;
280pub const DF_1_EDITED: u64 = 0x0020_0000;
282pub const DF_1_NORELOC: u64 = 0x0040_0000;
283pub const DF_1_SYMINTPOSE: u64 = 0x0080_0000;
285pub const DF_1_GLOBAUDIT: u64 = 0x0100_0000;
287pub const DF_1_SINGLETON: u64 = 0x0200_0000;
289pub const DF_1_PIE: u64 = 0x0800_0000;
291
292pub fn df_1_tag_to_str(tag: u64) -> &'static str {
293 match tag {
294 DF_1_NOW => "DF_1_NOW",
295 DF_1_GLOBAL => "DF_1_GLOBAL",
296 DF_1_GROUP => "DF_1_GROUP",
297 DF_1_NODELETE => "DF_1_NODELETE",
298 DF_1_LOADFLTR => "DF_1_LOADFLTR",
299 DF_1_INITFIRST => "DF_1_INITFIRST",
300 DF_1_NOOPEN => "DF_1_NOOPEN",
301 DF_1_ORIGIN => "DF_1_ORIGIN",
302 DF_1_DIRECT => "DF_1_DIRECT",
303 DF_1_TRANS => "DF_1_TRANS",
304 DF_1_INTERPOSE => "DF_1_INTERPOSE",
305 DF_1_NODEFLIB => "DF_1_NODEFLIB",
306 DF_1_NODUMP => "DF_1_NODUMP",
307 DF_1_CONFALT => "DF_1_CONFALT",
308 DF_1_ENDFILTEE => "DF_1_ENDFILTEE",
309 DF_1_DISPRELDNE => "DF_1_DISPRELDNE",
310 DF_1_DISPRELPND => "DF_1_DISPRELPND",
311 DF_1_NODIRECT => "DF_1_NODIRECT",
312 DF_1_IGNMULDEF => "DF_1_IGNMULDEF",
313 DF_1_NOKSYMS => "DF_1_NOKSYMS",
314 DF_1_NOHDR => "DF_1_NOHDR",
315 DF_1_EDITED => "DF_1_EDITED",
316 DF_1_NORELOC => "DF_1_NORELOC",
317 DF_1_SYMINTPOSE => "DF_1_SYMINTPOSE",
318 DF_1_GLOBAUDIT => "DF_1_GLOBAUDIT",
319 DF_1_SINGLETON => "DF_1_SINGLETON",
320 DF_1_PIE => "DF_1_PIE",
321 _ => "UNKNOWN_TAG",
322 }
323}
324
325if_alloc! {
326 use core::fmt;
327 use scroll::ctx;
328 use core::result;
329 use crate::container::{Ctx, Container};
330 use crate::strtab::Strtab;
331 use alloc::vec::Vec;
332
333 #[derive(Default, PartialEq, Clone)]
334 pub struct Dyn {
335 pub d_tag: u64,
336 pub d_val: u64,
337 }
338
339 impl Dyn {
340 #[inline]
341 pub fn size(container: Container) -> usize {
342 use scroll::ctx::SizeWith;
343 Self::size_with(&Ctx::from(container))
344 }
345 }
346
347 impl fmt::Debug for Dyn {
348 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
349 f.debug_struct("Dyn")
350 .field("d_tag", &tag_to_str(self.d_tag))
351 .field("d_val", &format_args!("0x{:x}", self.d_val))
352 .finish()
353 }
354 }
355
356 impl ctx::SizeWith<Ctx> for Dyn {
357 fn size_with(&Ctx { container, .. }: &Ctx) -> usize {
358 match container {
359 Container::Little => {
360 dyn32::SIZEOF_DYN
361 },
362 Container::Big => {
363 dyn64::SIZEOF_DYN
364 },
365 }
366 }
367 }
368
369 impl<'a> ctx::TryFromCtx<'a, Ctx> for Dyn {
370 type Error = crate::error::Error;
371 fn try_from_ctx(bytes: &'a [u8], Ctx { container, le}: Ctx) -> result::Result<(Self, usize), Self::Error> {
372 use scroll::Pread;
373 let dynamic = match container {
374 Container::Little => {
375 (bytes.pread_with::<dyn32::Dyn>(0, le)?.into(), dyn32::SIZEOF_DYN)
376 },
377 Container::Big => {
378 (bytes.pread_with::<dyn64::Dyn>(0, le)?.into(), dyn64::SIZEOF_DYN)
379 }
380 };
381 Ok(dynamic)
382 }
383 }
384
385 impl ctx::TryIntoCtx<Ctx> for Dyn {
386 type Error = crate::error::Error;
387 fn try_into_ctx(self, bytes: &mut [u8], Ctx { container, le}: Ctx) -> result::Result<usize, Self::Error> {
388 use scroll::Pwrite;
389 match container {
390 Container::Little => {
391 let dynamic: dyn32::Dyn = self.into();
392 Ok(bytes.pwrite_with(dynamic, 0, le)?)
393 },
394 Container::Big => {
395 let dynamic: dyn64::Dyn = self.into();
396 Ok(bytes.pwrite_with(dynamic, 0, le)?)
397 }
398 }
399 }
400 }
401
402 #[derive(Debug)]
403 pub struct Dynamic {
404 pub dyns: Vec<Dyn>,
405 pub info: DynamicInfo,
406 }
407
408 impl Dynamic {
409 #[cfg(feature = "endian_fd")]
410 pub fn parse(bytes: &[u8], phdrs: &[crate::elf::program_header::ProgramHeader], ctx: Ctx) -> crate::error::Result<Option<Self>> {
412 use scroll::ctx::SizeWith;
413 use scroll::Pread;
414 use crate::elf::program_header;
415 for phdr in phdrs {
416 if phdr.p_type == program_header::PT_DYNAMIC {
417 let offset = phdr.p_offset as usize;
418 let filesz = phdr.p_filesz as usize;
419 let bytes = if filesz > 0 {
421 bytes
422 .pread_with::<&[u8]>(offset, filesz)
423 .map_err(|_| crate::error::Error::Malformed(format!("Invalid PT_DYNAMIC size (offset {:#x}, filesz {:#x})",
424 offset, filesz)))?
425 } else {
426 &[]
427 };
428 let size = Dyn::size_with(&ctx);
429 let count = filesz / size;
431 let mut dyns = Vec::with_capacity(count);
432 let mut offset = 0;
433 for _ in 0..count {
434 let dynamic = bytes.gread_with::<Dyn>(&mut offset, ctx)?;
435 let tag = dynamic.d_tag;
436 dyns.push(dynamic);
437 if tag == DT_NULL { break }
438 }
439 let mut info = DynamicInfo::default();
440 for dynamic in &dyns {
441 info.update(phdrs, dynamic);
442 }
443 return Ok(Some(Dynamic { dyns: dyns, info: info, }));
444 }
445 }
446 Ok(None)
447 }
448
449 pub fn get_libraries<'a>(&self, strtab: &Strtab<'a>) -> Vec<&'a str> {
450 use log::warn;
451 let count = self.info.needed_count.min(self.dyns.len());
452 let mut needed = Vec::with_capacity(count);
453 for dynamic in &self.dyns {
454 if dynamic.d_tag as u64 == DT_NEEDED {
455 if let Some(lib) = strtab.get_at(dynamic.d_val as usize) {
456 needed.push(lib)
457 } else {
458 warn!("Invalid DT_NEEDED {}", dynamic.d_val)
459 }
460 }
461 }
462 needed
463 }
464 }
465}
466
467macro_rules! elf_dyn_std_impl {
468 ($size:ident, $phdr:ty) => {
469
470 #[cfg(test)]
471 mod tests {
472 use super::*;
473 #[test]
474 fn size_of() {
475 assert_eq!(::std::mem::size_of::<Dyn>(), SIZEOF_DYN);
476 }
477 }
478
479 if_alloc! {
480 use core::fmt;
481 use core::slice;
482 use alloc::vec::Vec;
483
484 use crate::elf::program_header::{PT_DYNAMIC};
485 use crate::strtab::Strtab;
486
487 use crate::elf::dynamic::Dyn as ElfDyn;
488
489 if_std! {
490 use std::fs::File;
491 use std::io::{Read, Seek};
492 use std::io::SeekFrom::Start;
493 use crate::error::Result;
494 }
495
496 impl From<ElfDyn> for Dyn {
497 fn from(dynamic: ElfDyn) -> Self {
498 Dyn {
499 d_tag: dynamic.d_tag as $size,
500 d_val: dynamic.d_val as $size,
501 }
502 }
503 }
504 impl From<Dyn> for ElfDyn {
505 fn from(dynamic: Dyn) -> Self {
506 ElfDyn {
507 d_tag: u64::from(dynamic.d_tag),
508 d_val: u64::from(dynamic.d_val),
509 }
510 }
511 }
512
513 impl fmt::Debug for Dyn {
514 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
515 f.debug_struct("Dyn")
516 .field("d_tag", &tag_to_str(u64::from(self.d_tag)))
517 .field("d_val", &format_args!("0x{:x}", self.d_val))
518 .finish()
519 }
520 }
521
522 #[cfg(feature = "std")]
524 pub fn from_fd(mut fd: &File, phdrs: &[$phdr]) -> Result<Option<Vec<Dyn>>> {
525 for phdr in phdrs {
526 if phdr.p_type == PT_DYNAMIC {
527 let filesz = phdr.p_filesz as usize;
529 let dync = filesz / SIZEOF_DYN;
530 let mut dyns = vec![Dyn::default(); dync];
531 fd.seek(Start(u64::from(phdr.p_offset)))?;
532 unsafe {
533 fd.read_exact(plain::as_mut_bytes(&mut *dyns))?;
534 }
535 dyns.dedup();
536 return Ok(Some(dyns));
537 }
538 }
539 Ok(None)
540 }
541
542 pub unsafe fn from_raw<'a>(bias: usize, vaddr: usize) -> &'a [Dyn] {
544 let dynp = vaddr.wrapping_add(bias) as *const Dyn;
545 let mut idx = 0;
546 while u64::from((*dynp.offset(idx)).d_tag) != DT_NULL {
547 idx += 1;
548 }
549 slice::from_raw_parts(dynp, idx as usize)
550 }
551
552 pub unsafe fn from_phdrs(bias: usize, phdrs: &[$phdr]) -> Option<&[Dyn]> {
556 for phdr in phdrs {
557 if phdr.p_type as u32 == PT_DYNAMIC {
559 return Some(from_raw(bias, phdr.p_vaddr as usize));
560 }
561 }
562 None
563 }
564
565 pub unsafe fn get_needed<'a>(dyns: &[Dyn], strtab: *const Strtab<'a>, count: usize) -> Vec<&'a str> {
567 let mut needed = Vec::with_capacity(count.min(dyns.len()));
568 for dynamic in dyns {
569 if u64::from(dynamic.d_tag) == DT_NEEDED {
570 let lib = &(*strtab)[dynamic.d_val as usize];
571 needed.push(lib);
572 }
573 }
574 needed
575 }
576 }
577 };
578}
579
580macro_rules! elf_dynamic_info_std_impl {
581 ($size:ident, $phdr:ty) => {
582 fn vm_to_offset(phdrs: &[$phdr], address: $size) -> Option<$size> {
584 for ph in phdrs {
585 if ph.p_type == crate::elf::program_header::PT_LOAD && address >= ph.p_vaddr {
586 let offset = address - ph.p_vaddr;
587 if offset < ph.p_memsz {
588 return ph.p_offset.checked_add(offset);
589 }
590 }
591 }
592 None
593 }
594
595 #[derive(Default, PartialEq)]
597 pub struct DynamicInfo {
598 pub rela: usize,
599 pub relasz: usize,
600 pub relaent: $size,
601 pub relacount: usize,
602 pub rel: usize,
603 pub relsz: usize,
604 pub relent: $size,
605 pub relcount: usize,
606 pub gnu_hash: Option<$size>,
607 pub hash: Option<$size>,
608 pub strtab: usize,
609 pub strsz: usize,
610 pub symtab: usize,
611 pub syment: usize,
612 pub pltgot: Option<$size>,
613 pub pltrelsz: usize,
614 pub pltrel: $size,
615 pub jmprel: usize,
616 pub verdef: $size,
617 pub verdefnum: $size,
618 pub verneed: $size,
619 pub verneednum: $size,
620 pub versym: $size,
621 pub init: $size,
622 pub fini: $size,
623 pub init_array: $size,
624 pub init_arraysz: usize,
625 pub fini_array: $size,
626 pub fini_arraysz: usize,
627 pub needed_count: usize,
628 pub flags: $size,
629 pub flags_1: $size,
630 pub soname: usize,
631 pub textrel: bool,
632 }
633
634 impl DynamicInfo {
635 #[inline]
636 pub fn update(&mut self, phdrs: &[$phdr], dynamic: &Dyn) {
637 match u64::from(dynamic.d_tag) {
638 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,
640 DT_RELAENT => self.relaent = dynamic.d_val as _,
641 DT_RELACOUNT => self.relacount = dynamic.d_val as usize,
642 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,
644 DT_RELENT => self.relent = dynamic.d_val as _,
645 DT_RELCOUNT => self.relcount = dynamic.d_val as usize,
646 DT_GNU_HASH => self.gnu_hash = vm_to_offset(phdrs, dynamic.d_val),
647 DT_HASH => self.hash = vm_to_offset(phdrs, dynamic.d_val),
648 DT_STRTAB => {
649 self.strtab = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0) as usize
650 }
651 DT_STRSZ => self.strsz = dynamic.d_val as usize,
652 DT_SYMTAB => {
653 self.symtab = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0) as usize
654 }
655 DT_SYMENT => self.syment = dynamic.d_val as usize,
656 DT_PLTGOT => self.pltgot = vm_to_offset(phdrs, dynamic.d_val),
657 DT_PLTRELSZ => self.pltrelsz = dynamic.d_val as usize,
658 DT_PLTREL => self.pltrel = dynamic.d_val as _,
659 DT_JMPREL => {
660 self.jmprel = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0) as usize
661 } DT_VERDEF => self.verdef = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0),
663 DT_VERDEFNUM => self.verdefnum = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0),
664 DT_VERNEED => self.verneed = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0),
665 DT_VERNEEDNUM => self.verneednum = dynamic.d_val as _,
666 DT_VERSYM => self.versym = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0),
667 DT_INIT => self.init = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0),
668 DT_FINI => self.fini = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0),
669 DT_INIT_ARRAY => {
670 self.init_array = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0)
671 }
672 DT_INIT_ARRAYSZ => self.init_arraysz = dynamic.d_val as _,
673 DT_FINI_ARRAY => {
674 self.fini_array = vm_to_offset(phdrs, dynamic.d_val).unwrap_or(0)
675 }
676 DT_FINI_ARRAYSZ => self.fini_arraysz = dynamic.d_val as _,
677 DT_NEEDED => self.needed_count += 1,
678 DT_FLAGS => self.flags = dynamic.d_val as _,
679 DT_FLAGS_1 => self.flags_1 = dynamic.d_val as _,
680 DT_SONAME => self.soname = dynamic.d_val as _,
681 DT_TEXTREL => self.textrel = true,
682 _ => (),
683 }
684 }
685 pub fn new(dynamic: &[Dyn], phdrs: &[$phdr]) -> DynamicInfo {
686 let mut info = DynamicInfo::default();
687 for dyna in dynamic {
688 info.update(phdrs, &dyna);
689 }
690 info
691 }
692 }
693
694 if_alloc! {
695 impl fmt::Debug for DynamicInfo {
696 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
697 let gnu_hash = self.gnu_hash.unwrap_or(0);
698 let hash = self.hash.unwrap_or(0);
699 let pltgot = self.pltgot.unwrap_or(0);
700
701 let flags: Vec<&'static str> = [DF_ORIGIN, DF_SYMBOLIC, DF_TEXTREL, DF_BIND_NOW, DF_STATIC_TLS,][..]
702 .iter()
703 .filter(|f| (self.flags as u64 & *f) != 0)
704 .map(|f| df_tag_to_str(*f))
705 .collect();
706
707 let flags_1: Vec<&'static str> = [
708 DF_1_NOW,
709 DF_1_GLOBAL,
710 DF_1_GROUP,
711 DF_1_NODELETE,
712 DF_1_LOADFLTR,
713 DF_1_INITFIRST,
714 DF_1_NOOPEN,
715 DF_1_ORIGIN,
716 DF_1_DIRECT,
717 DF_1_TRANS,
718 DF_1_INTERPOSE,
719 DF_1_NODEFLIB,
720 DF_1_NODUMP,
721 DF_1_CONFALT,
722 DF_1_ENDFILTEE,
723 DF_1_DISPRELDNE,
724 DF_1_DISPRELPND,
725 DF_1_NODIRECT,
726 DF_1_IGNMULDEF,
727 DF_1_NOKSYMS,
728 DF_1_NOHDR,
729 DF_1_EDITED,
730 DF_1_NORELOC,
731 DF_1_SYMINTPOSE,
732 DF_1_GLOBAUDIT,
733 DF_1_SINGLETON,
734 DF_1_PIE,
735 ][..]
736 .iter()
737 .filter(|f| (self.flags_1 as u64 & *f) != 0)
738 .map(|f| df_1_tag_to_str(*f))
739 .collect();
740
741 f.debug_struct("DynamicInfo")
742 .field("rela", &format_args!("0x{:x}", self.rela))
743 .field("relasz", &self.relasz)
744 .field("relaent", &self.relaent)
745 .field("relacount", &self.relacount)
746 .field("gnu_hash", &format_args!("0x{:x}", gnu_hash))
747 .field("hash", &format_args!("0x{:x}", hash))
748 .field("strtab", &format_args!("0x{:x}", self.strtab))
749 .field("strsz", &self.strsz)
750 .field("symtab", &format_args!("0x{:x}", self.symtab))
751 .field("syment", &self.syment)
752 .field("pltgot", &format_args!("0x{:x}", pltgot))
753 .field("pltrelsz", &self.pltrelsz)
754 .field("pltrel", &self.pltrel)
755 .field("jmprel", &format_args!("0x{:x}", self.jmprel))
756 .field("verdef", &format_args!("0x{:x}", self.verdef))
757 .field("verdefnum", &self.verdefnum)
758 .field("verneed", &format_args!("0x{:x}", self.verneed))
759 .field("verneednum", &self.verneednum)
760 .field("versym", &format_args!("0x{:x}", self.versym))
761 .field("init", &format_args!("0x{:x}", self.init))
762 .field("fini", &format_args!("0x{:x}", self.fini))
763 .field("init_array", &format_args!("{:#x}", self.init_array))
764 .field("init_arraysz", &self.init_arraysz)
765 .field("needed_count", &self.needed_count)
766 .field("flags", &format_args!("{:#0width$x} {:?}", self.flags, flags, width = core::mem::size_of_val(&self.flags)))
767 .field("flags_1", &format_args!("{:#0width$x} {:?}", self.flags_1, flags_1, width = core::mem::size_of_val(&self.flags_1)))
768 .field("soname", &self.soname)
769 .field("textrel", &self.textrel)
770 .finish()
771 }
772 }
773 }
774 };
775}
776
777if_alloc! {
778 elf_dynamic_info_std_impl!(u64, crate::elf::program_header::ProgramHeader);
779}
780
781pub mod dyn32 {
782 pub use crate::elf::dynamic::*;
783
784 elf_dyn!(u32);
785
786 pub const SIZEOF_DYN: usize = 8;
787
788 elf_dyn_std_impl!(u32, crate::elf32::program_header::ProgramHeader);
789 elf_dynamic_info_std_impl!(
790 u32,
791 crate::elf::program_header::program_header32::ProgramHeader
792 );
793}
794
795pub mod dyn64 {
796 pub use crate::elf::dynamic::*;
797
798 elf_dyn!(u64);
799
800 pub const SIZEOF_DYN: usize = 16;
801
802 elf_dyn_std_impl!(u64, crate::elf64::program_header::ProgramHeader);
803 elf_dynamic_info_std_impl!(
804 u64,
805 crate::elf::program_header::program_header64::ProgramHeader
806 );
807}