1use alloc::format;
2
3use crate::std::ops::Range;
4use crate::{
5 BinaryReader, BinaryReaderError, FromReader, Result, SectionLimited, Subsection, Subsections,
6};
7
8bitflags::bitflags! {
9 #[repr(transparent)]
15 #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
16 pub struct SymbolFlags: u32 {
17 const BINDING_WEAK = 1 << 0;
23 const BINDING_LOCAL = 1 << 1;
25 const VISIBILITY_HIDDEN = 1 << 2;
27 const UNDEFINED = 1 << 4;
29 const EXPORTED = 1 << 5;
31 const EXPLICIT_NAME = 1 << 6;
33 const NO_STRIP = 1 << 7;
35 const TLS = 1 << 8;
37 const ABSOLUTE = 1 << 9;
39 }
40
41 #[repr(transparent)]
46 #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
47 pub struct SegmentFlags: u32 {
48 const STRINGS = 0x1;
50 const TLS = 0x2;
52 }
53}
54
55impl<'a> FromReader<'a> for SymbolFlags {
56 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
57 Ok(Self::from_bits_retain(reader.read_var_u32()?))
58 }
59}
60
61impl<'a> FromReader<'a> for SegmentFlags {
62 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
63 Ok(Self::from_bits_retain(reader.read_var_u32()?))
64 }
65}
66
67#[derive(Debug, Clone)]
72pub struct LinkingSectionReader<'a> {
73 version: u32,
75 subsections: Subsections<'a, Linking<'a>>,
77 range: Range<usize>,
79}
80
81pub type SegmentMap<'a> = SectionLimited<'a, Segment<'a>>;
83
84#[derive(Debug, Copy, Clone)]
86pub struct Segment<'a> {
87 pub name: &'a str,
89 pub alignment: u32,
91 pub flags: SegmentFlags,
93}
94
95impl<'a> FromReader<'a> for Segment<'a> {
96 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
97 let name = reader.read_string()?;
98 let alignment = reader.read_var_u32()?;
99 let flags = reader.read()?;
100 Ok(Self {
101 name,
102 alignment,
103 flags,
104 })
105 }
106}
107
108pub type InitFuncMap<'a> = SectionLimited<'a, InitFunc>;
110
111#[derive(Debug, Copy, Clone)]
113pub struct InitFunc {
114 pub priority: u32,
116 pub symbol_index: u32,
118}
119
120impl<'a> FromReader<'a> for InitFunc {
121 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
122 let priority = reader.read_var_u32()?;
123 let symbol_index = reader.read_var_u32()?;
124 Ok(Self {
125 priority,
126 symbol_index,
127 })
128 }
129}
130
131pub type ComdatMap<'a> = SectionLimited<'a, Comdat<'a>>;
133
134#[derive(Debug, Clone)]
136pub struct Comdat<'a> {
137 pub name: &'a str,
139 pub flags: u32,
141 pub symbols: SectionLimited<'a, ComdatSymbol>,
143}
144
145impl<'a> FromReader<'a> for Comdat<'a> {
146 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
147 let name = reader.read_string()?;
148 let flags = reader.read_var_u32()?;
149 let symbols = SectionLimited::new(reader.remaining_buffer(), reader.original_position())?;
150 Ok(Self {
151 name,
152 flags,
153 symbols,
154 })
155 }
156}
157
158#[derive(Debug, Copy, Clone)]
160pub struct ComdatSymbol {
161 pub kind: ComdatSymbolKind,
163 pub index: u32,
165}
166
167impl<'a> FromReader<'a> for ComdatSymbol {
168 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
169 let kind = reader.read()?;
170 let index = reader.read_var_u32()?;
171 Ok(Self { kind, index })
172 }
173}
174
175#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
177pub enum ComdatSymbolKind {
178 Data,
180 Func,
182 Global,
184 Event,
186 Table,
188 Section,
190}
191
192impl<'a> FromReader<'a> for ComdatSymbolKind {
193 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
194 let offset = reader.original_position();
195 match reader.read_u8()? {
196 0 => Ok(Self::Data),
197 1 => Ok(Self::Func),
198 2 => Ok(Self::Global),
199 3 => Ok(Self::Event),
200 4 => Ok(Self::Table),
201 5 => Ok(Self::Section),
202 k => Err(BinaryReader::invalid_leading_byte_error(
203 k,
204 "comdat symbol kind",
205 offset,
206 )),
207 }
208 }
209}
210
211pub type SymbolInfoMap<'a> = SectionLimited<'a, SymbolInfo<'a>>;
213
214#[derive(Debug, Copy, Clone)]
220pub enum SymbolInfo<'a> {
221 Func {
223 flags: SymbolFlags,
225 index: u32,
227 name: Option<&'a str>,
229 },
230 Data {
232 flags: SymbolFlags,
234 name: &'a str,
236 symbol: Option<DefinedDataSymbol>,
238 },
239 Global {
241 flags: SymbolFlags,
243 index: u32,
245 name: Option<&'a str>,
247 },
248 Section {
250 flags: SymbolFlags,
252 section: u32,
254 },
255 Event {
257 flags: SymbolFlags,
259 index: u32,
261 name: Option<&'a str>,
263 },
264 Table {
266 flags: SymbolFlags,
268 index: u32,
270 name: Option<&'a str>,
272 },
273}
274
275impl<'a> FromReader<'a> for SymbolInfo<'a> {
276 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
277 let offset = reader.original_position();
278 let kind = reader.read_u8()?;
279 let flags: SymbolFlags = reader.read()?;
280
281 let defined = !flags.contains(SymbolFlags::UNDEFINED);
282 let explicit_name = flags.contains(SymbolFlags::EXPLICIT_NAME);
283
284 const SYMTAB_FUNCTION: u8 = 0;
285 const SYMTAB_DATA: u8 = 1;
286 const SYMTAB_GLOBAL: u8 = 2;
287 const SYMTAB_SECTION: u8 = 3;
288 const SYMTAB_EVENT: u8 = 4;
289 const SYMTAB_TABLE: u8 = 5;
290
291 match kind {
293 SYMTAB_FUNCTION | SYMTAB_GLOBAL | SYMTAB_EVENT | SYMTAB_TABLE => {
294 let index = reader.read_var_u32()?;
295 let name = match defined || explicit_name {
296 true => Some(reader.read_string()?),
297 false => None,
298 };
299 Ok(match kind {
300 SYMTAB_FUNCTION => Self::Func { flags, index, name },
301 SYMTAB_GLOBAL => Self::Global { flags, index, name },
302 SYMTAB_EVENT => Self::Event { flags, index, name },
303 SYMTAB_TABLE => Self::Table { flags, index, name },
304 _ => unreachable!(),
305 })
306 }
307 SYMTAB_DATA => {
308 let name = reader.read_string()?;
309 let data = match defined {
310 true => Some(reader.read()?),
311 false => None,
312 };
313 Ok(Self::Data {
314 flags,
315 name,
316 symbol: data,
317 })
318 }
319 SYMTAB_SECTION => {
320 let section = reader.read_var_u32()?;
321 Ok(Self::Section { flags, section })
322 }
323 k => Err(BinaryReader::invalid_leading_byte_error(
324 k,
325 "symbol kind",
326 offset,
327 )),
328 }
329 }
330}
331
332#[derive(Debug, Copy, Clone)]
334pub struct DefinedDataSymbol {
335 pub index: u32,
337 pub offset: u32,
339 pub size: u32,
341}
342
343impl<'a> FromReader<'a> for DefinedDataSymbol {
344 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
345 let index = reader.read_var_u32()?;
346 let offset = reader.read_var_u32()?;
347 let size = reader.read_var_u32()?;
348 Ok(Self {
349 index,
350 offset,
351 size,
352 })
353 }
354}
355
356#[derive(Debug, Clone)]
358pub enum Linking<'a> {
359 SegmentInfo(SegmentMap<'a>),
361 InitFuncs(InitFuncMap<'a>),
363 ComdatInfo(ComdatMap<'a>),
365 SymbolTable(SymbolInfoMap<'a>),
367 Unknown {
369 ty: u8,
371 data: &'a [u8],
373 range: Range<usize>,
376 },
377}
378
379impl<'a> Subsection<'a> for Linking<'a> {
380 fn from_reader(id: u8, reader: BinaryReader<'a>) -> Result<Self> {
381 let data = reader.remaining_buffer();
382 let offset = reader.original_position();
383 Ok(match id {
384 5 => Self::SegmentInfo(SegmentMap::new(data, offset)?),
385 6 => Self::InitFuncs(InitFuncMap::new(data, offset)?),
386 7 => Self::ComdatInfo(ComdatMap::new(data, offset)?),
387 8 => Self::SymbolTable(SymbolInfoMap::new(data, offset)?),
388 ty => Self::Unknown {
389 ty,
390 data,
391 range: offset..offset + data.len(),
392 },
393 })
394 }
395}
396
397impl<'a> LinkingSectionReader<'a> {
398 pub fn new(data: &'a [u8], offset: usize) -> Result<Self> {
401 let mut reader = BinaryReader::new_with_offset(data, offset);
402 let range = reader.range();
403
404 let version = reader.read_var_u32()?;
405 if version != 2 {
406 return Err(BinaryReaderError::new(
407 format!("unsupported linking section version: {}", version),
408 offset,
409 ));
410 }
411
412 let subsections = Subsections::new(reader.remaining_buffer(), reader.original_position());
413 Ok(Self {
414 version,
415 subsections,
416 range,
417 })
418 }
419
420 pub fn version(&self) -> u32 {
422 self.version
423 }
424
425 pub fn original_position(&self) -> usize {
427 self.subsections.original_position()
428 }
429
430 pub fn range(&self) -> Range<usize> {
433 self.range.clone()
434 }
435
436 pub fn subsections(&self) -> Subsections<'a, Linking<'a>> {
440 self.subsections.clone()
441 }
442}
443
444impl<'a> IntoIterator for LinkingSectionReader<'a> {
445 type Item = Result<Linking<'a>>;
446 type IntoIter = Subsections<'a, Linking<'a>>;
447
448 fn into_iter(self) -> Self::IntoIter {
449 self.subsections
450 }
451}