elf2flash_core/
address_range.rs1use elf::{ElfBytes, abi::PT_LOAD, endian::EndianParse};
2use thiserror::Error;
3
4#[derive(Copy, Clone, Debug, Eq, PartialEq)]
5pub enum AddressRangeType {
6 Contents,
8 NoContents,
10 Ignore,
12}
13
14#[derive(Copy, Clone, Debug)]
15pub struct AddressRange {
16 pub typ: AddressRangeType,
17 pub to: u64,
18 pub from: u64,
19}
20
21impl AddressRange {
22 pub const fn new(from: u64, to: u64, typ: AddressRangeType) -> Self {
23 Self { typ, to, from }
24 }
25}
26
27impl Default for AddressRange {
28 fn default() -> Self {
29 Self {
30 typ: AddressRangeType::Ignore,
31 to: 0,
32 from: 0,
33 }
34 }
35}
36
37#[derive(Error, Debug)]
38pub enum AddressRangesFromElfError {
39 #[error("No segments in ELF")]
40 NoSegments,
41 #[error("ELF contains memory contents for uninitialized memory at {0:08x}")]
42 MemoryContentsForUninitializedMemory(u64),
43 #[error("Memory segment {0:#08x}->{1:#08x} is outside of valid address range for device")]
44 MemorySegmentInvalidForDevice(u64, u64),
45}
46
47pub fn address_ranges_from_elf<E: EndianParse>(
48 file: &ElfBytes<'_, E>,
49) -> Result<Vec<AddressRange>, AddressRangesFromElfError> {
50 let segments = file
51 .segments()
52 .ok_or(AddressRangesFromElfError::NoSegments)?;
53
54 let mut ranges = Vec::new();
55
56 for seg in segments {
57 if seg.p_type != PT_LOAD || seg.p_memsz == 0 {
58 continue;
59 }
60
61 let start = seg.p_paddr;
62 let end = start + seg.p_memsz;
63
64 if seg.p_filesz > 0 {
65 ranges.push(AddressRange::new(
67 start,
68 start + seg.p_filesz,
69 AddressRangeType::Contents,
70 ));
71 }
72
73 if seg.p_memsz > seg.p_filesz {
74 ranges.push(AddressRange::new(
76 start + seg.p_filesz,
77 end,
78 AddressRangeType::NoContents,
79 ));
80 }
81 }
82
83 Ok(ranges)
84}