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// ============================================================================