1 use crate::errors::SectionMappingsError;
2 use crate::linux_ptrace_dumper::LinuxPtraceDumper;
3 use crate::maps_reader::MappingInfo;
4 use crate::minidump_format::*;
5 use crate::minidump_writer::{DumpBuf, MinidumpWriter};
6 use crate::sections::{write_string_to_location, MemoryArrayWriter, MemoryWriter};
7 
8 type Result<T> = std::result::Result<T, SectionMappingsError>;
9 
10 /// Write information about the mappings in effect. Because we are using the
11 /// minidump format, the information about the mappings is pretty limited.
12 /// Because of this, we also include the full, unparsed, /proc/$x/maps file in
13 /// another stream in the file.
write( config: &mut MinidumpWriter, buffer: &mut DumpBuf, dumper: &mut LinuxPtraceDumper, ) -> Result<MDRawDirectory>14 pub fn write(
15     config: &mut MinidumpWriter,
16     buffer: &mut DumpBuf,
17     dumper: &mut LinuxPtraceDumper,
18 ) -> Result<MDRawDirectory> {
19     let mut modules = Vec::new();
20 
21     // First write all the mappings from the dumper
22     for map_idx in 0..dumper.mappings.len() {
23         // If the mapping is uninteresting, or if
24         // there is caller-provided information about this mapping
25         // in the user_mapping_list list, skip it
26 
27         if !dumper.mappings[map_idx].is_interesting()
28             || dumper.mappings[map_idx].is_contained_in(&config.user_mapping_list)
29         {
30             continue;
31         }
32         // Note: elf_identifier_for_mapping_index() can manipulate the |mapping.name|.
33         let identifier = dumper
34             .elf_identifier_for_mapping_index(map_idx)
35             .unwrap_or_default();
36 
37         // If the identifier is all 0, its an uninteresting mapping (bmc#1676109)
38         if identifier.is_empty() || identifier.iter().all(|&x| x == 0) {
39             continue;
40         }
41 
42         let module = fill_raw_module(buffer, &dumper.mappings[map_idx], &identifier)?;
43         modules.push(module);
44     }
45 
46     // Next write all the mappings provided by the caller
47     for user in &config.user_mapping_list {
48         // GUID was provided by caller.
49         let module = fill_raw_module(buffer, &user.mapping, &user.identifier)?;
50         modules.push(module)
51     }
52 
53     let list_header = MemoryWriter::<u32>::alloc_with_val(buffer, modules.len() as u32)?;
54 
55     let mut dirent = MDRawDirectory {
56         stream_type: MDStreamType::ModuleListStream as u32,
57         location: list_header.location(),
58     };
59 
60     if !modules.is_empty() {
61         let mapping_list = MemoryArrayWriter::<MDRawModule>::alloc_from_array(buffer, &modules)?;
62         dirent.location.data_size += mapping_list.location().data_size;
63     }
64 
65     Ok(dirent)
66 }
67 
fill_raw_module( buffer: &mut DumpBuf, mapping: &MappingInfo, identifier: &[u8], ) -> Result<MDRawModule>68 fn fill_raw_module(
69     buffer: &mut DumpBuf,
70     mapping: &MappingInfo,
71     identifier: &[u8],
72 ) -> Result<MDRawModule> {
73     let cv_record: MDLocationDescriptor;
74     if identifier.is_empty() {
75         // Just zeroes
76         cv_record = Default::default();
77     } else {
78         let cv_signature = MD_CVINFOELF_SIGNATURE;
79         let array_size = std::mem::size_of_val(&cv_signature) + identifier.len();
80 
81         let mut sig_section = MemoryArrayWriter::<u8>::alloc_array(buffer, array_size)?;
82         for (index, val) in cv_signature
83             .to_ne_bytes()
84             .iter()
85             .chain(identifier.iter())
86             .enumerate()
87         {
88             sig_section.set_value_at(buffer, *val, index)?;
89         }
90         cv_record = sig_section.location();
91     }
92 
93     let (file_path, _) = mapping
94         .get_mapping_effective_name_and_path()
95         .map_err(|e| SectionMappingsError::GetEffectivePathError(mapping.clone(), e))?;
96     let name_header = write_string_to_location(buffer, &file_path)?;
97 
98     Ok(MDRawModule {
99         base_of_image: mapping.start_address as u64,
100         size_of_image: mapping.size as u32,
101         cv_record,
102         module_name_rva: name_header.rva,
103         ..Default::default()
104     })
105 }
106