]> git.proxmox.com Git - rustc.git/blob - vendor/goblin/src/pe/debug.rs
New upstream version 1.48.0+dfsg1
[rustc.git] / vendor / goblin / src / pe / debug.rs
1 use crate::error;
2 use scroll::{Pread, Pwrite, SizeWith};
3
4 use crate::pe::data_directories;
5 use crate::pe::section_table;
6 use crate::pe::utils;
7
8 #[derive(Debug, PartialEq, Copy, Clone, Default)]
9 pub struct DebugData<'a> {
10 pub image_debug_directory: ImageDebugDirectory,
11 pub codeview_pdb70_debug_info: Option<CodeviewPDB70DebugInfo<'a>>,
12 }
13
14 impl<'a> DebugData<'a> {
15 pub fn parse(
16 bytes: &'a [u8],
17 dd: data_directories::DataDirectory,
18 sections: &[section_table::SectionTable],
19 file_alignment: u32,
20 ) -> error::Result<Self> {
21 let image_debug_directory =
22 ImageDebugDirectory::parse(bytes, dd, sections, file_alignment)?;
23 let codeview_pdb70_debug_info =
24 CodeviewPDB70DebugInfo::parse(bytes, &image_debug_directory)?;
25
26 Ok(DebugData {
27 image_debug_directory,
28 codeview_pdb70_debug_info,
29 })
30 }
31
32 /// Return this executable's debugging GUID, suitable for matching against a PDB file.
33 pub fn guid(&self) -> Option<[u8; 16]> {
34 self.codeview_pdb70_debug_info.map(|pdb70| pdb70.signature)
35 }
36 }
37
38 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680307(v=vs.85).aspx
39 #[repr(C)]
40 #[derive(Debug, PartialEq, Copy, Clone, Default, Pread, Pwrite, SizeWith)]
41 pub struct ImageDebugDirectory {
42 pub characteristics: u32,
43 pub time_date_stamp: u32,
44 pub major_version: u16,
45 pub minor_version: u16,
46 pub data_type: u32,
47 pub size_of_data: u32,
48 pub address_of_raw_data: u32,
49 pub pointer_to_raw_data: u32,
50 }
51
52 pub const IMAGE_DEBUG_TYPE_UNKNOWN: u32 = 0;
53 pub const IMAGE_DEBUG_TYPE_COFF: u32 = 1;
54 pub const IMAGE_DEBUG_TYPE_CODEVIEW: u32 = 2;
55 pub const IMAGE_DEBUG_TYPE_FPO: u32 = 3;
56 pub const IMAGE_DEBUG_TYPE_MISC: u32 = 4;
57 pub const IMAGE_DEBUG_TYPE_EXCEPTION: u32 = 5;
58 pub const IMAGE_DEBUG_TYPE_FIXUP: u32 = 6;
59 pub const IMAGE_DEBUG_TYPE_BORLAND: u32 = 9;
60
61 impl ImageDebugDirectory {
62 fn parse(
63 bytes: &[u8],
64 dd: data_directories::DataDirectory,
65 sections: &[section_table::SectionTable],
66 file_alignment: u32,
67 ) -> error::Result<Self> {
68 let rva = dd.virtual_address as usize;
69 let offset = utils::find_offset(rva, sections, file_alignment).ok_or_else(|| {
70 error::Error::Malformed(format!(
71 "Cannot map ImageDebugDirectory rva {:#x} into offset",
72 rva
73 ))
74 })?;
75 let idd: Self = bytes.pread_with(offset, scroll::LE)?;
76 Ok(idd)
77 }
78 }
79
80 pub const CODEVIEW_PDB70_MAGIC: u32 = 0x5344_5352;
81 pub const CODEVIEW_PDB20_MAGIC: u32 = 0x3031_424e;
82 pub const CODEVIEW_CV50_MAGIC: u32 = 0x3131_424e;
83 pub const CODEVIEW_CV41_MAGIC: u32 = 0x3930_424e;
84
85 // http://llvm.org/doxygen/CVDebugRecord_8h_source.html
86 #[repr(C)]
87 #[derive(Debug, PartialEq, Copy, Clone, Default)]
88 pub struct CodeviewPDB70DebugInfo<'a> {
89 pub codeview_signature: u32,
90 pub signature: [u8; 16],
91 pub age: u32,
92 pub filename: &'a [u8],
93 }
94
95 impl<'a> CodeviewPDB70DebugInfo<'a> {
96 pub fn parse(bytes: &'a [u8], idd: &ImageDebugDirectory) -> error::Result<Option<Self>> {
97 if idd.data_type != IMAGE_DEBUG_TYPE_CODEVIEW {
98 // not a codeview debug directory
99 // that's not an error, but it's not a CodeviewPDB70DebugInfo either
100 return Ok(None);
101 }
102
103 // ImageDebugDirectory.pointer_to_raw_data stores a raw offset -- not a virtual offset -- which we can use directly
104 let mut offset: usize = idd.pointer_to_raw_data as usize;
105
106 // calculate how long the eventual filename will be, which doubles as a check of the record size
107 let filename_length = idd.size_of_data as isize - 24;
108 if filename_length < 0 || filename_length > 1024 {
109 // the record is too short or too long to be plausible
110 return Err(error::Error::Malformed(format!(
111 "ImageDebugDirectory size of data seems wrong: {:?}",
112 idd.size_of_data
113 )));
114 }
115 let filename_length = filename_length as usize;
116
117 // check the codeview signature
118 let codeview_signature: u32 = bytes.gread_with(&mut offset, scroll::LE)?;
119 if codeview_signature != CODEVIEW_PDB70_MAGIC {
120 return Ok(None);
121 }
122
123 // read the rest
124 let mut signature: [u8; 16] = [0; 16];
125 signature.copy_from_slice(bytes.gread_with(&mut offset, 16)?);
126 let age: u32 = bytes.gread_with(&mut offset, scroll::LE)?;
127 let filename = &bytes[offset..offset + filename_length];
128
129 Ok(Some(CodeviewPDB70DebugInfo {
130 codeview_signature,
131 signature,
132 age,
133 filename,
134 }))
135 }
136 }