ms_pdb/dbi/fixups.rs
1//! Definitions relating to the `FIXUP_DATA` Optional Debug Substream.
2
3use super::*;
4use crate::Pdb;
5
6/// Describes a fixup record, stored in the `FIXUP_DATA` Optional Debug Substream.
7///
8/// This _does not_ describe the structure of a relocation record (stored in the PE binary itself).
9/// Instead, this structure describes "fixups" (which are essentially relocation records) that are
10/// stored in the `FIXUP_DATA` Optional Debug Substream. These records allow binary analysis tools
11/// to discover relationships between code (and between code and data) that are not otherwise
12/// represented in the PE binary itself.
13#[allow(missing_docs)]
14#[repr(C)]
15#[derive(Clone, Default, Debug, FromBytes, Immutable, IntoBytes, KnownLayout)]
16pub struct Fixup {
17 /// Relocation type
18 ///
19 /// This is one of the `IMAGE_REL_*` constants. See the documentation for PE relocations.
20 /// These values are architecture-dependent; the same numeric values may have different
21 /// meanings on different architectures.
22 pub fixup_type: u16,
23 pub extra: u16,
24 pub rva: u32,
25 pub rva_target: u32,
26}
27
28impl<F: ReadAt> Pdb<F> {
29 /// Reads (uncached) the `FIXUP_DATA` optional debug stream.
30 pub fn read_fixups(&self) -> anyhow::Result<Option<Vec<Fixup>>> {
31 let Some(fixup_stream_index) = self.fixup_stream()? else {
32 return Ok(None);
33 };
34
35 let sr = self.get_stream_reader(fixup_stream_index)?;
36 let num_records = sr.stream_size() as usize / size_of::<Fixup>();
37 let mut fixups: Vec<Fixup> = Fixup::new_vec_zeroed(num_records).unwrap();
38 sr.read_exact_at(fixups.as_mut_bytes(), 0)?;
39 Ok(Some(fixups))
40 }
41}