1
1
use crate :: error;
2
+ use scroll:: ctx:: SizeWith ;
2
3
use scroll:: { Pread , Pwrite , SizeWith } ;
3
4
4
5
use crate :: pe:: data_directories;
@@ -8,6 +9,9 @@ use crate::pe::utils;
8
9
9
10
#[ derive( Debug , PartialEq , Copy , Clone , Default ) ]
10
11
pub struct DebugData < ' a > {
12
+ // TODO: There can be more than one ImageDebugDirectory.
13
+ // To avoid breaking the public API here, we just return the ImageDebugDirectory that has the
14
+ // `IMAGE_DEBUG_TYPE_CODEVIEW` type, or the last one if none has a codeview record.
11
15
pub image_debug_directory : ImageDebugDirectory ,
12
16
pub codeview_pdb70_debug_info : Option < CodeviewPDB70DebugInfo < ' a > > ,
13
17
}
@@ -35,14 +39,36 @@ impl<'a> DebugData<'a> {
35
39
file_alignment : u32 ,
36
40
opts : & options:: ParseOptions ,
37
41
) -> error:: Result < Self > {
38
- let image_debug_directory =
39
- ImageDebugDirectory :: parse_with_opts ( bytes, dd, sections, file_alignment, opts) ?;
40
- let codeview_pdb70_debug_info =
41
- CodeviewPDB70DebugInfo :: parse_with_opts ( bytes, & image_debug_directory, opts) ?;
42
-
42
+ let rva = dd. virtual_address as usize ;
43
+ let mut offset =
44
+ utils:: find_offset ( rva, sections, file_alignment, opts) . ok_or_else ( || {
45
+ error:: Error :: Malformed ( format ! (
46
+ "Cannot map ImageDebugDirectory rva {:#x} into offset" ,
47
+ rva
48
+ ) )
49
+ } ) ?;
50
+
51
+ let len = dd. size as usize ;
52
+ let sizeof_directory = ImageDebugDirectory :: size_with ( & scroll:: LE ) ;
53
+ let num_entries = len / sizeof_directory;
54
+
55
+ let mut entries = ( 0 ..num_entries)
56
+ . map ( |_| bytes. gread_with ( & mut offset, scroll:: LE ) )
57
+ . collect :: < Result < Vec < ImageDebugDirectory > , _ > > ( ) ?;
58
+
59
+ // find the debug directory that references the codeview record
60
+ for ( idx, idd) in entries. iter ( ) . enumerate ( ) {
61
+ if let Some ( cv_record) = CodeviewPDB70DebugInfo :: parse_with_opts ( bytes, idd, opts) ? {
62
+ return Ok ( DebugData {
63
+ image_debug_directory : entries[ idx] ,
64
+ codeview_pdb70_debug_info : Some ( cv_record) ,
65
+ } ) ;
66
+ }
67
+ }
68
+ // if we don't have a codeview record, just return the last debug directory
43
69
Ok ( DebugData {
44
- image_debug_directory,
45
- codeview_pdb70_debug_info,
70
+ image_debug_directory : entries . pop ( ) . unwrap ( ) ,
71
+ codeview_pdb70_debug_info : None ,
46
72
} )
47
73
}
48
74
@@ -75,42 +101,6 @@ pub const IMAGE_DEBUG_TYPE_EXCEPTION: u32 = 5;
75
101
pub const IMAGE_DEBUG_TYPE_FIXUP : u32 = 6 ;
76
102
pub const IMAGE_DEBUG_TYPE_BORLAND : u32 = 9 ;
77
103
78
- impl ImageDebugDirectory {
79
- #[ allow( unused) ]
80
- fn parse (
81
- bytes : & [ u8 ] ,
82
- dd : data_directories:: DataDirectory ,
83
- sections : & [ section_table:: SectionTable ] ,
84
- file_alignment : u32 ,
85
- ) -> error:: Result < Self > {
86
- Self :: parse_with_opts (
87
- bytes,
88
- dd,
89
- sections,
90
- file_alignment,
91
- & options:: ParseOptions :: default ( ) ,
92
- )
93
- }
94
-
95
- fn parse_with_opts (
96
- bytes : & [ u8 ] ,
97
- dd : data_directories:: DataDirectory ,
98
- sections : & [ section_table:: SectionTable ] ,
99
- file_alignment : u32 ,
100
- opts : & options:: ParseOptions ,
101
- ) -> error:: Result < Self > {
102
- let rva = dd. virtual_address as usize ;
103
- let offset = utils:: find_offset ( rva, sections, file_alignment, opts) . ok_or_else ( || {
104
- error:: Error :: Malformed ( format ! (
105
- "Cannot map ImageDebugDirectory rva {:#x} into offset" ,
106
- rva
107
- ) )
108
- } ) ?;
109
- let idd: Self = bytes. pread_with ( offset, scroll:: LE ) ?;
110
- Ok ( idd)
111
- }
112
- }
113
-
114
104
pub const CODEVIEW_PDB70_MAGIC : u32 = 0x5344_5352 ;
115
105
pub const CODEVIEW_PDB20_MAGIC : u32 = 0x3031_424e ;
116
106
pub const CODEVIEW_CV50_MAGIC : u32 = 0x3131_424e ;
0 commit comments