summaryrefslogtreecommitdiffstats
path: root/third_party/rust/minidump-writer/src/linux/sections/mappings.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/minidump-writer/src/linux/sections/mappings.rs')
-rw-r--r--third_party/rust/minidump-writer/src/linux/sections/mappings.rs98
1 files changed, 98 insertions, 0 deletions
diff --git a/third_party/rust/minidump-writer/src/linux/sections/mappings.rs b/third_party/rust/minidump-writer/src/linux/sections/mappings.rs
new file mode 100644
index 0000000000..7eb002d036
--- /dev/null
+++ b/third_party/rust/minidump-writer/src/linux/sections/mappings.rs
@@ -0,0 +1,98 @@
+use super::*;
+use crate::linux::maps_reader::MappingInfo;
+
+/// Write information about the mappings in effect. Because we are using the
+/// minidump format, the information about the mappings is pretty limited.
+/// Because of this, we also include the full, unparsed, /proc/$x/maps file in
+/// another stream in the file.
+pub fn write(
+ config: &mut MinidumpWriter,
+ buffer: &mut DumpBuf,
+ dumper: &mut PtraceDumper,
+) -> Result<MDRawDirectory, errors::SectionMappingsError> {
+ let mut modules = Vec::new();
+
+ // First write all the mappings from the dumper
+ for map_idx in 0..dumper.mappings.len() {
+ // If the mapping is uninteresting, or if
+ // there is caller-provided information about this mapping
+ // in the user_mapping_list list, skip it
+
+ if !dumper.mappings[map_idx].is_interesting()
+ || dumper.mappings[map_idx].is_contained_in(&config.user_mapping_list)
+ {
+ continue;
+ }
+ // Note: elf_identifier_for_mapping_index() can manipulate the |mapping.name|.
+ let identifier = dumper
+ .elf_identifier_for_mapping_index(map_idx)
+ .unwrap_or_default();
+
+ // If the identifier is all 0, its an uninteresting mapping (bmc#1676109)
+ if identifier.is_empty() || identifier.iter().all(|&x| x == 0) {
+ continue;
+ }
+
+ let module = fill_raw_module(buffer, &dumper.mappings[map_idx], &identifier)?;
+ modules.push(module);
+ }
+
+ // Next write all the mappings provided by the caller
+ for user in &config.user_mapping_list {
+ // GUID was provided by caller.
+ let module = fill_raw_module(buffer, &user.mapping, &user.identifier)?;
+ modules.push(module);
+ }
+
+ let list_header = MemoryWriter::<u32>::alloc_with_val(buffer, modules.len() as u32)?;
+
+ let mut dirent = MDRawDirectory {
+ stream_type: MDStreamType::ModuleListStream as u32,
+ location: list_header.location(),
+ };
+
+ if !modules.is_empty() {
+ let mapping_list = MemoryArrayWriter::<MDRawModule>::alloc_from_iter(buffer, modules)?;
+ dirent.location.data_size += mapping_list.location().data_size;
+ }
+
+ Ok(dirent)
+}
+
+fn fill_raw_module(
+ buffer: &mut DumpBuf,
+ mapping: &MappingInfo,
+ identifier: &[u8],
+) -> Result<MDRawModule, errors::SectionMappingsError> {
+ let cv_record = if identifier.is_empty() {
+ // Just zeroes
+ Default::default()
+ } else {
+ let cv_signature = crate::minidump_format::format::CvSignature::Elf as u32;
+ let array_size = std::mem::size_of_val(&cv_signature) + identifier.len();
+
+ let mut sig_section = MemoryArrayWriter::<u8>::alloc_array(buffer, array_size)?;
+ for (index, val) in cv_signature
+ .to_ne_bytes()
+ .iter()
+ .chain(identifier.iter())
+ .enumerate()
+ {
+ sig_section.set_value_at(buffer, *val, index)?;
+ }
+ sig_section.location()
+ };
+
+ let (file_path, _) = mapping
+ .get_mapping_effective_name_and_path()
+ .map_err(|e| errors::SectionMappingsError::GetEffectivePathError(mapping.clone(), e))?;
+ let name_header = write_string_to_location(buffer, &file_path)?;
+
+ Ok(MDRawModule {
+ base_of_image: mapping.start_address as u64,
+ size_of_image: mapping.size as u32,
+ cv_record,
+ module_name_rva: name_header.rva,
+ ..Default::default()
+ })
+}