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