@@ -107,6 +107,19 @@ impl<'s> DebugInformation<'s> {
107107 let contributions_buf = buf. take ( self . header . section_contribution_size as usize ) ?;
108108 DBISectionContributionIter :: parse ( contributions_buf. into ( ) )
109109 }
110+
111+ /// Returns an iterator that can traverse the section map in sequential order. Also known as the "OMF Segment map".
112+ pub fn section_map ( & self ) -> Result < DBISectionMapIter < ' _ > > {
113+ let mut buf = self . stream . parse_buffer ( ) ;
114+ // drop the header, modules list, and section contributions list
115+ let offset = self . header_len +
116+ self . header . module_list_size as usize +
117+ self . header . section_contribution_size as usize ;
118+
119+ buf. take ( offset) ?;
120+ let section_map_buf = buf. take ( self . header . section_map_size as usize ) ?;
121+ DBISectionMapIter :: parse ( section_map_buf. into ( ) )
122+ }
110123}
111124
112125/// The version of the PDB format.
@@ -584,6 +597,83 @@ impl<'c> FallibleIterator for DBISectionContributionIter<'c> {
584597 }
585598}
586599
600+ /// See https://github.com/google/syzygy/blob/8164b24ebde9c5649c9a09e88a7fc0b0fcbd1bc5/syzygy/pdb/pdb_data.h#L172
601+ /// Also see https://www.virtualbox.org/browser/vbox/trunk/include/iprt/formats/codeview.h?rev=93115#L272
602+ /// This is also known as OMF Segment Map. In the OMF SegmentMap structure, flags and section_type
603+ /// are a single 16-bit value.
604+ #[ derive( Debug , Copy , Clone ) ]
605+ pub struct DBISectionMapItem {
606+ /// flags: 0x1 read, 0x2 write, 0x4 execute, 0x8 32-bit
607+ pub flags : u8 ,
608+ /// section_type: 0x1 = SEL, 0x2 = ABS, 0x10 = GROUP
609+ pub section_type : u8 ,
610+ /// Overlay number
611+ pub overlay : u16 ,
612+ /// group index, 0 if not relevant
613+ pub group : u16 ,
614+ /// Technically "frame" in OMF SegmentMap, which is complicated
615+ pub section_number : u16 ,
616+ /// Index into name table, or 0xffff
617+ pub seg_name_index : u16 ,
618+ /// Index into name table, or 0xffff
619+ pub class_name_index : u16 ,
620+ /// RVA offset of this section
621+ pub rva_offset : u32 ,
622+ /// Length of this section
623+ pub section_length : u32 ,
624+ }
625+
626+
627+ impl DBISectionMapItem {
628+ fn parse ( buf : & mut ParseBuffer < ' _ > ) -> Result < Self > {
629+ Ok ( Self {
630+ flags : buf. parse_u8 ( ) ?,
631+ section_type : buf. parse_u8 ( ) ?,
632+ overlay : buf. parse_u16 ( ) ?,
633+ group : buf. parse_u16 ( ) ?,
634+ section_number : buf. parse_u16 ( ) ?,
635+ seg_name_index : buf. parse_u16 ( ) ?,
636+ class_name_index : buf. parse_u16 ( ) ?,
637+ rva_offset : buf. parse_u32 ( ) ?,
638+ section_length : buf. parse_u32 ( ) ?,
639+ } )
640+ }
641+ }
642+
643+ /// A `DBISectionMapIter` iterates over the section map in the DBI section, producing `DBISectionMap`s.
644+ #[ derive( Debug ) ]
645+ pub struct DBISectionMapIter < ' c > {
646+ /// The section count.
647+ pub sec_count : u16 ,
648+ /// The logical section count. Typically equals sec_count, if no groups are in use. (?)
649+ pub sec_count_log : u16 ,
650+ buf : ParseBuffer < ' c > ,
651+ }
652+
653+ impl < ' c > DBISectionMapIter < ' c > {
654+ fn parse ( mut buf : ParseBuffer < ' c > ) -> Result < Self > {
655+ let sec_count = buf. parse_u16 ( ) ?;
656+ let sec_count_log = buf. parse_u16 ( ) ?;
657+
658+ Ok ( Self { buf, sec_count, sec_count_log } )
659+ }
660+ }
661+
662+ impl < ' c > FallibleIterator for DBISectionMapIter < ' c > {
663+ type Item = DBISectionMapItem ;
664+ type Error = Error ;
665+
666+ fn next ( & mut self ) -> result:: Result < Option < Self :: Item > , Self :: Error > {
667+ // see if we're at EOF
668+ if self . buf . is_empty ( ) {
669+ return Ok ( None ) ;
670+ }
671+
672+ let segmap = Self :: Item :: parse ( & mut self . buf ) ?;
673+ Ok ( Some ( segmap) )
674+ }
675+ }
676+
587677/// A `DbgDataHdr`, which contains a series of (optional) MSF stream numbers.
588678#[ derive( Debug , Copy , Clone ) ]
589679#[ allow( dead_code) ] // reason = "unused fields added for completeness"
0 commit comments