1use crate::StreamData;
8use crate::dbi::ModuleInfoFixed;
9use crate::utils::vec::replace_range_copy;
10use crate::{dbi::ModuleInfo, syms::SymIter};
11use anyhow::{Result, anyhow, bail};
12use ms_codeview::parser::Parser;
13use std::mem::size_of;
14use std::ops::Range;
15use sync_file::ReadAt;
16use tracing::{debug, warn};
17use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, LE, U32, Unaligned};
18
19#[derive(IntoBytes, FromBytes, Immutable, KnownLayout, Unaligned)]
22#[repr(C)]
23pub struct ModuleSymbolsHeader {
24 pub signature: U32<LE>,
27}
28
29const MODULE_SYMBOLS_HEADER_LEN: usize = 4;
30static_assertions::const_assert_eq!(size_of::<ModuleSymbolsHeader>(), MODULE_SYMBOLS_HEADER_LEN);
31
32pub const CV_SIGNATURE_C6: u32 = 0;
34pub const CV_SIGNATURE_C7: u32 = 1;
36pub const CV_SIGNATURE_C11: u32 = 2;
38pub const CV_SIGNATURE_C13: u32 = 4;
40pub const CV_SIGNATURE_RESERVED: u32 = 5;
42
43impl<F: ReadAt> crate::Pdb<F> {
44 pub fn read_module_stream(
49 &self,
50 mod_info: &ModuleInfo,
51 ) -> Result<Option<ModiStreamData<StreamData>>, anyhow::Error> {
52 let Some(stream) = mod_info.stream() else {
53 return Ok(None);
54 };
55
56 let stream_data = self.read_stream(stream)?;
57 Ok(Some(ModiStreamData::new(stream_data, mod_info.header())?))
58 }
59
60 pub fn read_module_symbols(&self, module: &ModuleInfo) -> Result<Vec<u32>> {
69 let len_u32 = module.sym_size() as usize / 4;
70 if len_u32 < 4 {
71 return Ok(Vec::new());
72 }
73
74 let Some(module_stream) = module.stream() else {
75 return Ok(Vec::new());
76 };
77
78 let mut syms: Vec<u32> = vec![0; len_u32];
79 let sr = self.get_stream_reader(module_stream)?;
80 sr.read_exact_at(syms.as_mut_bytes(), 0)?;
81 Ok(syms)
82 }
83}
84
85#[allow(missing_docs)]
87pub struct ModiStreamData<Data> {
88 pub stream_data: Data,
90 pub sym_byte_size: u32,
91 pub c11_byte_size: u32,
92 pub c13_byte_size: u32,
93 pub global_refs_size: u32,
94}
95
96impl<Data: AsRef<[u8]>> ModiStreamData<Data> {
97 pub fn new(stream_data: Data, module: &ModuleInfoFixed) -> anyhow::Result<Self> {
100 let stream_bytes: &[u8] = stream_data.as_ref();
101
102 let sym_byte_size = module.sym_byte_size.get();
104 let c11_byte_size = module.c11_byte_size.get();
105 let c13_byte_size = module.c13_byte_size.get();
106
107 let mut p = Parser::new(stream_bytes);
108
109 p.skip(sym_byte_size as usize).map_err(|_| {
110 anyhow!("Module info has a sym_byte_size that exceeds the size of the stream.")
111 })?;
112 p.skip(c11_byte_size as usize).map_err(|_| {
113 anyhow!("Module info has a c11_byte_size that exceeds the size of the stream.")
114 })?;
115 p.skip(c13_byte_size as usize).map_err(|_| {
116 anyhow!("Module info has a c13_byte_size that exceeds the size of the stream.")
117 })?;
118
119 let mut global_refs_size;
120 if !p.is_empty() {
121 global_refs_size = p
122 .u32()
123 .map_err(|_| anyhow!("Failed to decode global_refs_size. There are {} bytes after the module symbols substream.", p.len()))?;
124
125 if global_refs_size == 0xffff_ffff {
126 warn!("Module has global_refs_size = 0xffff_ffff");
127 global_refs_size = 0;
128 } else {
129 p.skip(global_refs_size as usize)
130 .map_err(|_| anyhow!("Failed to decode global_refs substream. global_refs_size = 0x{:x}, but there are only 0x{:x} bytes left.",
131 global_refs_size,
132 p.len()
133 ))?;
134 }
135
136 if !p.is_empty() {
137 debug!(stream_len = p.len(), "Module stream has extra bytes at end");
138 }
139 } else {
140 global_refs_size = 0;
141 }
142
143 Ok(Self {
144 stream_data,
145 sym_byte_size,
146 c11_byte_size,
147 c13_byte_size,
148 global_refs_size,
149 })
150 }
151
152 pub fn iter_syms(&self) -> SymIter<'_> {
154 if let Ok(sym_data) = self.sym_data() {
155 SymIter::new(sym_data)
156 } else {
157 SymIter::new(&[])
158 }
159 }
160
161 fn nested_slice(&self, range: Range<usize>) -> Result<&[u8]> {
162 if let Some(b) = self.stream_data.as_ref().get(range) {
163 Ok(b)
164 } else {
165 bail!("Range within module stream is invalid")
166 }
167 }
168
169 fn nested_slice_mut(&mut self, range: Range<usize>) -> Result<&mut [u8]>
170 where
171 Data: AsMut<[u8]>,
172 {
173 if let Some(b) = self.stream_data.as_mut().get_mut(range) {
174 Ok(b)
175 } else {
176 bail!("Range within module stream is invalid")
177 }
178 }
179
180 pub fn sym_data(&self) -> Result<&[u8]> {
184 self.nested_slice(MODULE_SYMBOLS_HEADER_LEN..self.sym_byte_size as usize)
185 }
186
187 pub fn sym_data_mut(&mut self) -> Result<&mut [u8]>
191 where
192 Data: AsMut<[u8]>,
193 {
194 self.nested_slice_mut(MODULE_SYMBOLS_HEADER_LEN..self.sym_byte_size as usize)
195 }
196
197 pub fn full_sym_data(&self) -> Result<&[u8]> {
201 self.nested_slice(0..self.sym_byte_size as usize)
202 }
203
204 pub fn full_sym_data_mut(&mut self) -> Result<&mut [u8]>
208 where
209 Data: AsMut<[u8]>,
210 {
211 self.nested_slice_mut(0..self.sym_byte_size as usize)
212 }
213
214 pub fn c13_line_data_range(&self) -> Range<usize> {
216 if self.c13_byte_size == 0 {
217 return 0..0;
218 }
219
220 let start = self.sym_byte_size as usize + self.c11_byte_size as usize;
221 start..start + self.c13_byte_size as usize
222 }
223
224 pub fn c13_line_data_bytes(&self) -> &[u8] {
226 if self.c13_byte_size == 0 {
227 return &[];
228 }
229
230 let stream_data: &[u8] = self.stream_data.as_ref();
232 let range = self.c13_line_data_range();
233 &stream_data[range]
234 }
235
236 pub fn c13_line_data_bytes_mut(&mut self) -> &mut [u8]
238 where
239 Data: AsMut<[u8]>,
240 {
241 if self.c13_byte_size == 0 {
242 return &mut [];
243 }
244
245 let range = self.c13_line_data_range();
247 let stream_data: &mut [u8] = self.stream_data.as_mut();
248 &mut stream_data[range]
249 }
250
251 pub fn c13_line_data(&self) -> crate::lines::LineData<'_> {
253 crate::lines::LineData::new(self.c13_line_data_bytes())
254 }
255
256 pub fn c13_line_data_mut(&mut self) -> crate::lines::LineDataMut<'_>
258 where
259 Data: AsMut<[u8]>,
260 {
261 crate::lines::LineDataMut::new(self.c13_line_data_bytes_mut())
262 }
263
264 pub fn global_refs_range(&self) -> Range<usize> {
266 if self.global_refs_size == 0 {
267 return 0..0;
268 }
269
270 let global_refs_offset = self.sym_byte_size as usize
274 + self.c11_byte_size as usize
275 + self.c13_byte_size as usize
276 + size_of::<U32<LE>>();
277 global_refs_offset..global_refs_offset + self.global_refs_size as usize
278 }
279
280 pub fn global_refs(&self) -> Result<&[U32<LE>]> {
285 let range = self.global_refs_range();
286 let stream_data: &[u8] = self.stream_data.as_ref();
287 if let Some(global_refs_bytes) = stream_data.get(range) {
288 if let Ok(global_refs) = FromBytes::ref_from_bytes(global_refs_bytes) {
289 Ok(global_refs)
290 } else {
291 bail!("Invalid size for global refs")
292 }
293 } else {
294 bail!("Invalid range for global refs")
295 }
296 }
297
298 pub fn global_refs_mut(&mut self) -> Result<&mut [U32<LE>]>
300 where
301 Data: AsMut<[u8]>,
302 {
303 let range = self.global_refs_range();
304 let stream_data: &mut [u8] = self.stream_data.as_mut();
305 if let Some(global_refs_bytes) = stream_data.get_mut(range) {
306 if let Ok(global_refs) = FromBytes::mut_from_bytes(global_refs_bytes) {
307 Ok(global_refs)
308 } else {
309 bail!("Invalid size for global refs")
310 }
311 } else {
312 bail!("Invalid range for global refs")
313 }
314 }
315}
316
317impl ModiStreamData<Vec<u8>> {
318 pub fn replace_sym_data(&mut self, new_sym_data: &[u8]) {
320 if new_sym_data.len() == self.sym_byte_size as usize {
321 self.stream_data[..new_sym_data.len()].copy_from_slice(new_sym_data);
322 } else {
323 replace_range_copy(
324 &mut self.stream_data,
325 0,
326 self.sym_byte_size as usize,
327 new_sym_data,
328 );
329 self.sym_byte_size = new_sym_data.len() as u32;
330 }
331 }
332
333 pub fn truncate_global_refs(&mut self) {
335 if self.global_refs_size == 0 {
336 return;
337 }
338
339 let global_refs_offset =
340 self.sym_byte_size as usize + self.c11_byte_size as usize + self.c13_byte_size as usize;
341
342 self.stream_data.truncate(global_refs_offset);
343 self.global_refs_size = 0;
344 }
345}