summaryrefslogtreecommitdiffstats
path: root/third_party/rust/minidump-writer/src/dir_section.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/minidump-writer/src/dir_section.rs')
-rw-r--r--third_party/rust/minidump-writer/src/dir_section.rs103
1 files changed, 103 insertions, 0 deletions
diff --git a/third_party/rust/minidump-writer/src/dir_section.rs b/third_party/rust/minidump-writer/src/dir_section.rs
new file mode 100644
index 0000000000..ced5a2d156
--- /dev/null
+++ b/third_party/rust/minidump-writer/src/dir_section.rs
@@ -0,0 +1,103 @@
+use crate::{
+ mem_writer::{Buffer, MemoryArrayWriter, MemoryWriterError},
+ minidump_format::MDRawDirectory,
+};
+use std::io::{Error, Seek, Write};
+
+pub type DumpBuf = Buffer;
+
+#[derive(Debug, thiserror::Error)]
+pub enum FileWriterError {
+ #[error("IO error")]
+ IOError(#[from] Error),
+ #[error("Failed to write to memory")]
+ MemoryWriterError(#[from] MemoryWriterError),
+}
+
+/// Utility that wraps writing minidump directory entries to an I/O stream, generally
+/// a [`std::fs::File`].
+#[derive(Debug)]
+pub struct DirSection<'a, W>
+where
+ W: Write + Seek,
+{
+ curr_idx: usize,
+ section: MemoryArrayWriter<MDRawDirectory>,
+ /// If we have to append to some file, we have to know where we currently are
+ destination_start_offset: u64,
+ destination: &'a mut W,
+ last_position_written_to_file: u64,
+}
+
+impl<'a, W> DirSection<'a, W>
+where
+ W: Write + Seek,
+{
+ pub fn new(
+ buffer: &mut DumpBuf,
+ index_length: u32,
+ destination: &'a mut W,
+ ) -> std::result::Result<Self, FileWriterError> {
+ let dir_section =
+ MemoryArrayWriter::<MDRawDirectory>::alloc_array(buffer, index_length as usize)?;
+
+ Ok(Self {
+ curr_idx: 0,
+ section: dir_section,
+ destination_start_offset: destination.stream_position()?,
+ destination,
+ last_position_written_to_file: 0,
+ })
+ }
+
+ #[inline]
+ pub fn position(&self) -> u32 {
+ self.section.position
+ }
+
+ pub fn dump_dir_entry(
+ &mut self,
+ buffer: &mut DumpBuf,
+ dirent: MDRawDirectory,
+ ) -> std::result::Result<(), FileWriterError> {
+ self.section.set_value_at(buffer, dirent, self.curr_idx)?;
+
+ // Now write it to file
+
+ // First get all the positions
+ let curr_file_pos = self.destination.stream_position()?;
+ let idx_pos = self.section.location_of_index(self.curr_idx);
+ self.curr_idx += 1;
+
+ self.destination.seek(std::io::SeekFrom::Start(
+ self.destination_start_offset + idx_pos.rva as u64,
+ ))?;
+ let start = idx_pos.rva as usize;
+ let end = (idx_pos.rva + idx_pos.data_size) as usize;
+ self.destination.write_all(&buffer[start..end])?;
+
+ // Reset file-position
+ self.destination
+ .seek(std::io::SeekFrom::Start(curr_file_pos))?;
+
+ Ok(())
+ }
+
+ /// Writes 2 things to file:
+ /// 1. The given dirent into the dir section in the header (if any is given)
+ /// 2. Everything in the in-memory buffer that was added since the last call to this function
+ pub fn write_to_file(
+ &mut self,
+ buffer: &mut DumpBuf,
+ dirent: Option<MDRawDirectory>,
+ ) -> std::result::Result<(), FileWriterError> {
+ if let Some(dirent) = dirent {
+ self.dump_dir_entry(buffer, dirent)?;
+ }
+
+ let start_pos = self.last_position_written_to_file as usize;
+ self.destination.write_all(&buffer[start_pos..])?;
+ self.last_position_written_to_file = buffer.position();
+ Ok(())
+ }
+}