1use crate::prelude::*;
2use crate::{
3 BinaryReader, BinaryReaderError, FromReader, Result, SectionLimited, Subsection, Subsections,
4};
5use core::ops::Range;
6
7bitflags::bitflags! {
8 #[repr(transparent)]
14 #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
15 pub struct SymbolFlags: u32 {
16 const BINDING_WEAK = 1 << 0;
22 const BINDING_LOCAL = 1 << 1;
24 const VISIBILITY_HIDDEN = 1 << 2;
26 const UNDEFINED = 1 << 4;
28 const EXPORTED = 1 << 5;
30 const EXPLICIT_NAME = 1 << 6;
32 const NO_STRIP = 1 << 7;
34 const TLS = 1 << 8;
36 const ABSOLUTE = 1 << 9;
38 }
39
40 #[repr(transparent)]
45 #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
46 pub struct SegmentFlags: u32 {
47 const STRINGS = 0x1;
49 const TLS = 0x2;
51 }
52}
53
54impl<'a> FromReader<'a> for SymbolFlags {
55 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
56 Ok(Self::from_bits_retain(reader.read_var_u32()?))
57 }
58}
59
60impl<'a> FromReader<'a> for SegmentFlags {
61 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
62 Ok(Self::from_bits_retain(reader.read_var_u32()?))
63 }
64}
65
66#[derive(Debug, Clone)]
71pub struct LinkingSectionReader<'a> {
72 version: u32,
74 subsections: Subsections<'a, Linking<'a>>,
76 range: Range<usize>,
78}
79
80pub type SegmentMap<'a> = SectionLimited<'a, Segment<'a>>;
82
83#[derive(Debug, Copy, Clone)]
85pub struct Segment<'a> {
86 pub name: &'a str,
88 pub alignment: u32,
90 pub flags: SegmentFlags,
92}
93
94impl<'a> FromReader<'a> for Segment<'a> {
95 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
96 let name = reader.read_string()?;
97 let alignment = reader.read_var_u32()?;
98 let flags = reader.read()?;
99 Ok(Self {
100 name,
101 alignment,
102 flags,
103 })
104 }
105}
106
107pub type InitFuncMap<'a> = SectionLimited<'a, InitFunc>;
109
110#[derive(Debug, Copy, Clone)]
112pub struct InitFunc {
113 pub priority: u32,
115 pub symbol_index: u32,
117}
118
119impl<'a> FromReader<'a> for InitFunc {
120 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
121 let priority = reader.read_var_u32()?;
122 let symbol_index = reader.read_var_u32()?;
123 Ok(Self {
124 priority,
125 symbol_index,
126 })
127 }
128}
129
130pub type ComdatMap<'a> = SectionLimited<'a, Comdat<'a>>;
132
133#[derive(Debug, Clone)]
135pub struct Comdat<'a> {
136 pub name: &'a str,
138 pub flags: u32,
140 pub symbols: SectionLimited<'a, ComdatSymbol>,
142}
143
144impl<'a> FromReader<'a> for Comdat<'a> {
145 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
146 let name = reader.read_string()?;
147 let flags = reader.read_var_u32()?;
148 let symbols = reader.skip(|reader| {
150 let count = reader.read_var_u32()?;
151 for _ in 0..count {
152 reader.read::<ComdatSymbol>()?;
153 }
154 Ok(())
155 })?;
156 Ok(Self {
157 name,
158 flags,
159 symbols: SectionLimited::new(symbols)?,
160 })
161 }
162}
163
164#[derive(Debug, Copy, Clone)]
166pub struct ComdatSymbol {
167 pub kind: ComdatSymbolKind,
169 pub index: u32,
171}
172
173impl<'a> FromReader<'a> for ComdatSymbol {
174 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
175 let kind = reader.read()?;
176 let index = reader.read_var_u32()?;
177 Ok(Self { kind, index })
178 }
179}
180
181#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
183pub enum ComdatSymbolKind {
184 Data,
186 Func,
188 Global,
190 Event,
192 Table,
194 Section,
196}
197
198impl<'a> FromReader<'a> for ComdatSymbolKind {
199 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
200 let offset = reader.original_position();
201 match reader.read_u8()? {
202 0 => Ok(Self::Data),
203 1 => Ok(Self::Func),
204 2 => Ok(Self::Global),
205 3 => Ok(Self::Event),
206 4 => Ok(Self::Table),
207 5 => Ok(Self::Section),
208 k => Err(BinaryReader::invalid_leading_byte_error(
209 k,
210 "comdat symbol kind",
211 offset,
212 )),
213 }
214 }
215}
216
217pub type SymbolInfoMap<'a> = SectionLimited<'a, SymbolInfo<'a>>;
219
220#[derive(Debug, Copy, Clone)]
226pub enum SymbolInfo<'a> {
227 Func {
229 flags: SymbolFlags,
231 index: u32,
233 name: Option<&'a str>,
235 },
236 Data {
238 flags: SymbolFlags,
240 name: &'a str,
242 symbol: Option<DefinedDataSymbol>,
244 },
245 Global {
247 flags: SymbolFlags,
249 index: u32,
251 name: Option<&'a str>,
253 },
254 Section {
256 flags: SymbolFlags,
258 section: u32,
260 },
261 Event {
263 flags: SymbolFlags,
265 index: u32,
267 name: Option<&'a str>,
269 },
270 Table {
272 flags: SymbolFlags,
274 index: u32,
276 name: Option<&'a str>,
278 },
279}
280
281impl<'a> FromReader<'a> for SymbolInfo<'a> {
282 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
283 let offset = reader.original_position();
284 let kind = reader.read_u8()?;
285 let flags: SymbolFlags = reader.read()?;
286
287 let defined = !flags.contains(SymbolFlags::UNDEFINED);
288 let explicit_name = flags.contains(SymbolFlags::EXPLICIT_NAME);
289
290 const SYMTAB_FUNCTION: u8 = 0;
291 const SYMTAB_DATA: u8 = 1;
292 const SYMTAB_GLOBAL: u8 = 2;
293 const SYMTAB_SECTION: u8 = 3;
294 const SYMTAB_EVENT: u8 = 4;
295 const SYMTAB_TABLE: u8 = 5;
296
297 match kind {
299 SYMTAB_FUNCTION | SYMTAB_GLOBAL | SYMTAB_EVENT | SYMTAB_TABLE => {
300 let index = reader.read_var_u32()?;
301 let name = match defined || explicit_name {
302 true => Some(reader.read_string()?),
303 false => None,
304 };
305 Ok(match kind {
306 SYMTAB_FUNCTION => Self::Func { flags, index, name },
307 SYMTAB_GLOBAL => Self::Global { flags, index, name },
308 SYMTAB_EVENT => Self::Event { flags, index, name },
309 SYMTAB_TABLE => Self::Table { flags, index, name },
310 _ => unreachable!(),
311 })
312 }
313 SYMTAB_DATA => {
314 let name = reader.read_string()?;
315 let data = match defined {
316 true => Some(reader.read()?),
317 false => None,
318 };
319 Ok(Self::Data {
320 flags,
321 name,
322 symbol: data,
323 })
324 }
325 SYMTAB_SECTION => {
326 let section = reader.read_var_u32()?;
327 Ok(Self::Section { flags, section })
328 }
329 k => Err(BinaryReader::invalid_leading_byte_error(
330 k,
331 "symbol kind",
332 offset,
333 )),
334 }
335 }
336}
337
338#[derive(Debug, Copy, Clone)]
340pub struct DefinedDataSymbol {
341 pub index: u32,
343 pub offset: u32,
345 pub size: u32,
347}
348
349impl<'a> FromReader<'a> for DefinedDataSymbol {
350 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
351 let index = reader.read_var_u32()?;
352 let offset = reader.read_var_u32()?;
353 let size = reader.read_var_u32()?;
354 Ok(Self {
355 index,
356 offset,
357 size,
358 })
359 }
360}
361
362#[derive(Debug, Clone)]
364pub enum Linking<'a> {
365 SegmentInfo(SegmentMap<'a>),
367 InitFuncs(InitFuncMap<'a>),
369 ComdatInfo(ComdatMap<'a>),
371 SymbolTable(SymbolInfoMap<'a>),
373 Unknown {
375 ty: u8,
377 data: &'a [u8],
379 range: Range<usize>,
382 },
383}
384
385impl<'a> Subsection<'a> for Linking<'a> {
386 fn from_reader(id: u8, reader: BinaryReader<'a>) -> Result<Self> {
387 let data = reader.remaining_buffer();
388 let offset = reader.original_position();
389 Ok(match id {
390 5 => Self::SegmentInfo(SegmentMap::new(reader)?),
391 6 => Self::InitFuncs(InitFuncMap::new(reader)?),
392 7 => Self::ComdatInfo(ComdatMap::new(reader)?),
393 8 => Self::SymbolTable(SymbolInfoMap::new(reader)?),
394 ty => Self::Unknown {
395 ty,
396 data,
397 range: offset..offset + data.len(),
398 },
399 })
400 }
401}
402
403impl<'a> LinkingSectionReader<'a> {
404 pub fn new(mut reader: BinaryReader<'a>) -> Result<Self> {
407 let range = reader.range();
408 let offset = reader.original_position();
409
410 let version = reader.read_var_u32()?;
411 if version != 2 {
412 return Err(BinaryReaderError::new(
413 format!("unsupported linking section version: {}", version),
414 offset,
415 ));
416 }
417
418 let subsections = Subsections::new(reader.shrink());
419 Ok(Self {
420 version,
421 subsections,
422 range,
423 })
424 }
425
426 pub fn version(&self) -> u32 {
428 self.version
429 }
430
431 pub fn original_position(&self) -> usize {
433 self.subsections.original_position()
434 }
435
436 pub fn range(&self) -> Range<usize> {
439 self.range.clone()
440 }
441
442 pub fn subsections(&self) -> Subsections<'a, Linking<'a>> {
446 self.subsections.clone()
447 }
448}
449
450impl<'a> IntoIterator for LinkingSectionReader<'a> {
451 type Item = Result<Linking<'a>>;
452 type IntoIter = Subsections<'a, Linking<'a>>;
453
454 fn into_iter(self) -> Self::IntoIter {
455 self.subsections
456 }
457}