neotron_loader/
sections.rs1use crate::{Error, Loader, Source};
10
11#[derive(Debug, Clone)]
25pub struct Header {
26 sh_name_offset: u32,
27 sh_type: u32,
28 sh_flags: u32,
29 sh_addr: u32,
30 sh_offset: u32,
31 sh_size: u32,
32 sh_link: u32,
33 sh_info: u32,
34 sh_addralign: u32,
35 sh_entsize: u32,
36}
37
38impl Header {
39 pub const SIZE_IN_BYTES: u16 = 0x28;
41
42 pub const SHT_NULL: u32 = 0x0;
44
45 pub const SHT_PROGBITS: u32 = 0x1;
47
48 pub const SHT_SYMTAB: u32 = 0x2;
50
51 pub const SHT_STRTAB: u32 = 0x3;
53
54 pub const SHT_RELA: u32 = 0x4;
56
57 pub const SHT_HASH: u32 = 0x5;
59
60 pub const SHT_DYNAMIC: u32 = 0x6;
62
63 pub const SHT_NOTE: u32 = 0x7;
65
66 pub const SHT_NOBITS: u32 = 0x8;
68
69 pub const SHT_REL: u32 = 0x9;
71
72 pub const SHT_DYNSYM: u32 = 0x0B;
74
75 pub const SHT_INIT_ARRAY: u32 = 0x0E;
77
78 pub const SHT_FINI_ARRAY: u32 = 0x0F;
80
81 pub const SHT_PREINIT_ARRAY: u32 = 0x10;
83
84 pub const SHT_GROUP: u32 = 0x11;
86
87 pub const SHT_SYMTAB_SHNDX: u32 = 0x12;
89
90 pub fn new<DS>(loader: &Loader<DS>, idx: u16) -> Result<Self, Error<DS::Error>>
92 where
93 DS: Source,
94 {
95 let section_table_offset = loader.e_shoff + u32::from(Self::SIZE_IN_BYTES) * u32::from(idx);
96
97 let sh_name_offset = loader.data_source.read_u32_le(section_table_offset)?;
98 let sh_type = loader
99 .data_source
100 .read_u32_le(section_table_offset + 0x04)?;
101 let sh_flags = loader
102 .data_source
103 .read_u32_le(section_table_offset + 0x08)?;
104 let sh_addr = loader
105 .data_source
106 .read_u32_le(section_table_offset + 0x0C)?;
107 let sh_offset = loader
108 .data_source
109 .read_u32_le(section_table_offset + 0x10)?;
110 let sh_size = loader
111 .data_source
112 .read_u32_le(section_table_offset + 0x14)?;
113 let sh_link = loader
114 .data_source
115 .read_u32_le(section_table_offset + 0x18)?;
116 let sh_info = loader
117 .data_source
118 .read_u32_le(section_table_offset + 0x1C)?;
119 let sh_addralign = loader
120 .data_source
121 .read_u32_le(section_table_offset + 0x20)?;
122 let sh_entsize = loader
123 .data_source
124 .read_u32_le(section_table_offset + 0x24)?;
125
126 Ok(Self {
127 sh_name_offset,
128 sh_type,
129 sh_flags,
130 sh_addr,
131 sh_offset,
132 sh_size,
133 sh_link,
134 sh_info,
135 sh_addralign,
136 sh_entsize,
137 })
138 }
139
140 pub fn sh_name_offset(&self) -> u32 {
142 self.sh_name_offset
143 }
144
145 pub fn sh_name<'a, DS: Source>(
147 &self,
148 loader: &Loader<DS>,
149 buffer: &'a mut [u8],
150 ) -> Result<&'a str, Error<DS::Error>> {
151 let string_section_idx = loader.e_shstrndx;
152 let string_section_header = Self::new(loader, string_section_idx)?;
153 let string_start = string_section_header.sh_offset + self.sh_name_offset;
154
155 for b in buffer.iter_mut() {
156 *b = 0x00;
157 }
158
159 loader.data_source.read(string_start, buffer)?;
160
161 let cstr =
163 core::ffi::CStr::from_bytes_until_nul(buffer).map_err(|_| Error::NotEnoughSpace)?;
164
165 if let Ok(s) = cstr.to_str() {
166 Ok(s)
167 } else {
168 Err(Error::InvalidString)
169 }
170 }
171
172 pub fn sh_type(&self) -> u32 {
174 self.sh_type
175 }
176
177 pub fn sh_flags(&self) -> u32 {
179 self.sh_flags
180 }
181
182 pub fn sh_addr(&self) -> u32 {
184 self.sh_addr
185 }
186
187 pub fn sh_offset(&self) -> u32 {
189 self.sh_offset
190 }
191
192 pub fn sh_size(&self) -> u32 {
194 self.sh_size
195 }
196
197 pub fn sh_link(&self) -> u32 {
199 self.sh_link
200 }
201
202 pub fn sh_info(&self) -> u32 {
204 self.sh_info
205 }
206
207 pub fn sh_addralign(&self) -> u32 {
209 self.sh_addralign
210 }
211
212 pub fn sh_entsize(&self) -> u32 {
214 self.sh_entsize
215 }
216}
217
218