neotron_loader/
segments.rs

1//! Code and types for handling Segments.
2//!
3//! These live in the program header table. They are useful for building loaders.
4
5// ============================================================================
6// Imports
7// ============================================================================
8
9use crate::{Error, Loader, Source};
10
11// ============================================================================
12// Constants
13// ============================================================================
14
15// ============================================================================
16// Static Variables
17// ============================================================================
18
19// ============================================================================
20// Types
21// ============================================================================
22
23/// Represents a program header
24#[derive(Debug, Clone)]
25pub struct Header {
26    p_type: u32,
27    p_offset: u32,
28    p_vaddr: u32,
29    p_paddr: u32,
30    p_filesz: u32,
31    p_memsz: u32,
32    p_flags: u32,
33    p_align: u32,
34}
35
36impl Header {
37    /// Size of a program header entry
38    pub const SIZE_IN_BYTES: u16 = 0x20;
39
40    /// Program header table entry unused.
41    pub const PT_NULL: u32 = 0x00000000;
42    /// Loadable segment.
43    pub const PT_LOAD: u32 = 0x00000001;
44    /// Dynamic linking information.
45    pub const PT_DYNAMIC: u32 = 0x00000002;
46    /// Interpreter information.
47    pub const PT_INTERP: u32 = 0x00000003;
48    /// Auxiliary information.
49    pub const PT_NOTE: u32 = 0x00000004;
50    /// Reserved.
51    pub const PT_SHLIB: u32 = 0x00000005;
52    /// Segment containing program header table itself.
53    pub const PT_PHDR: u32 = 0x00000006;
54    /// Thread-Local Storage template.
55    pub const PT_TLS: u32 = 0x00000007;
56    /// Stack.
57    pub const PT_GNU_STACK: u32 = 0x6474E551;
58
59    /// Create a new section header.
60    pub fn new<DS>(loader: &Loader<DS>, idx: u16) -> Result<Self, Error<DS::Error>>
61    where
62        DS: Source,
63    {
64        let ph_table_offset = loader.e_phoff + u32::from(Self::SIZE_IN_BYTES) * u32::from(idx);
65
66        let p_type = loader.data_source.read_u32_le(ph_table_offset)?;
67        let p_offset = loader.data_source.read_u32_le(ph_table_offset + 0x04)?;
68        let p_vaddr = loader.data_source.read_u32_le(ph_table_offset + 0x08)?;
69        let p_paddr = loader.data_source.read_u32_le(ph_table_offset + 0x0C)?;
70        let p_filesz = loader.data_source.read_u32_le(ph_table_offset + 0x10)?;
71        let p_memsz = loader.data_source.read_u32_le(ph_table_offset + 0x14)?;
72        let p_flags = loader.data_source.read_u32_le(ph_table_offset + 0x18)?;
73        let p_align = loader.data_source.read_u32_le(ph_table_offset + 0x1C)?;
74
75        Ok(Self {
76            p_type,
77            p_offset,
78            p_vaddr,
79            p_paddr,
80            p_filesz,
81            p_memsz,
82            p_flags,
83            p_align,
84        })
85    }
86
87    /// Get the `p_type` field.
88    ///
89    /// This is the type of segment, e.g. `PT_LOAD`.
90    pub fn p_type(&self) -> u32 {
91        self.p_type
92    }
93
94    /// Get the `p_offset` field
95    ///
96    /// This is the start of the segment data within this ELF file.
97    pub fn p_offset(&self) -> u32 {
98        self.p_offset
99    }
100
101    /// Get the `p_vaddr` field
102    ///
103    /// This is the virtual memory load address.
104    pub fn p_vaddr(&self) -> u32 {
105        self.p_vaddr
106    }
107
108    /// Get the `p_paddr` field
109    ///
110    /// This is the physical memory load address.
111    pub fn p_paddr(&self) -> u32 {
112        self.p_paddr
113    }
114
115    /// Get the `p_filesz` field
116    ///
117    /// This is how much space is used by this segment on disk.
118    pub fn p_filesz(&self) -> u32 {
119        self.p_filesz
120    }
121
122    /// Get the `p_memsz` field
123    ///
124    /// This is how much space is used by this segment in RAM.
125    pub fn p_memsz(&self) -> u32 {
126        self.p_memsz
127    }
128
129    /// Get the `p_flags` field
130    ///
131    /// A bitfield indicating whether the segment is executable (`0x01`),
132    /// writable (`0x02`) or readable (`0x04`).
133    pub fn p_flags(&self) -> u32 {
134        self.p_flags
135    }
136
137    /// Get the `p_align` field
138    ///
139    /// 0 or 1 means no alignment, otherwise is a power-of-2 indicating
140    /// alignment for this segment.
141    pub fn p_align(&self) -> u32 {
142        self.p_align
143    }
144}
145
146// ============================================================================
147// Functions
148// ============================================================================
149
150// ============================================================================
151// Tests
152// ============================================================================
153
154// ============================================================================
155// End of File
156// ============================================================================