Skip to main content

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}