Skip to content

Commit

Permalink
Bug 1847098 - Add version number of so files
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexandre Lissy committed Feb 23, 2024
1 parent a098f7c commit 66010e0
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 9 deletions.
175 changes: 170 additions & 5 deletions src/linux/maps_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,62 @@ impl MappingInfo {
Ok(soname.to_string())
}

pub fn get_mapping_effective_path_and_name(&self) -> Result<(PathBuf, String)> {
fn elf_file_so_version(&self) -> (u32, u32, u32) {
// Report the so version from the filename as two u32 that will fit into
// version_info.file_version_{hi,lo}
let name = String::from(
self.name
.clone()
.expect("Failure to clone")
.to_str()
.unwrap(),
);

if !(name.contains(".so.")) {
return (0, 0, 0);
}

let filename = match name.split('/').last() {
Some(f) => f,
None => return (0, 0, 0),
};

match filename.split(".so.").last() {
Some(s) => {
let mut got_non_digit = false;
let vers: Vec<u32> = s
.split('.')
.collect::<Vec<&str>>()
.into_iter()
.map(|n| {
n.parse().unwrap_or_else(|_| {
got_non_digit = true;
0
})
})
.collect::<Vec<u32>>();

if got_non_digit {
return (0, 0, 0);
}

let (major, minor, release) = match vers.len() {
0 => (0, 0, 0),
1 => (vers[0], 0, 0),
2 => (vers[0], vers[1], 0),
3 => (vers[0], vers[1], vers[2]),
_ => (vers[0], vers[1], vers[2]),
};

(major, minor, release)
}
None => (0, 0, 0),
}
}

pub fn get_mapping_effective_path_name_and_version(
&self,
) -> Result<(PathBuf, String, (u32, u32, u32))> {
let mut file_path = PathBuf::from(self.name.clone().unwrap_or_default());

// Tools such as minidump_stackwalk use the name of the module to look up
Expand All @@ -321,7 +376,7 @@ impl MappingInfo {
.file_name()
.map(|s| s.to_string_lossy().into_owned())
.unwrap_or_default();
return Ok((file_path, file_name));
return Ok((file_path, file_name, self.elf_file_so_version()));
};

if self.is_executable() && self.offset != 0 {
Expand All @@ -337,7 +392,7 @@ impl MappingInfo {
file_path.set_file_name(&file_name);
}

Ok((file_path, file_name))
Ok((file_path, file_name, self.elf_file_so_version()))
}

pub fn is_contained_in(&self, user_mapping_list: &MappingList) -> bool {
Expand Down Expand Up @@ -628,13 +683,123 @@ a4840000-a4873000 rw-p 09021000 08:12 393449 /data/app/org.mozilla.firefox-1
);
assert_eq!(mappings.len(), 1);

let (file_path, file_name) = mappings[0]
.get_mapping_effective_path_and_name()
let (file_path, file_name, _version) = mappings[0]
.get_mapping_effective_path_name_and_version()
.expect("Couldn't get effective name for mapping");
assert_eq!(file_name, "libmozgtk.so");
assert_eq!(file_path, PathBuf::from("/home/martin/Documents/mozilla/devel/mozilla-central/obj/widget/gtk/mozgtk/gtk3/libmozgtk.so"));
}

#[test]
#[allow(clippy::identity_op)] // we want to be explicit on how versions are manipulated
#[allow(clippy::erasing_op)]
fn test_get_mapping_effective_version() {
let mappings = get_mappings_for(
"\
7f877ab9f000-7f877aba0000 rw-p 0001f000 00:1b 100457459 /home/alex/bin/firefox/libmozsandbox.so
7f877ae65000-7f877ae68000 rw-p 00265000 00:1b 90432393 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.32
7f877ae76000-7f877ae77000 rw-p 0000a000 00:1b 90443112 /usr/lib/x86_64-linux-gnu/libcairo-gobject.so.2.11800.0
7f877ae7c000-7f877ae8c000 r--p 00000000 00:1b 93439971 /usr/lib/x86_64-linux-gnu/libm.so.6
7f877af70000-7f877af71000 rw-p 00003000 00:1b 93439980 /usr/lib/x86_64-linux-gnu/libpthread.so.0
7f877af78000-7f877af79000 rw-p 00005000 00:1b 90423049 /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0.7800.0
7f877ae7c000-7f877ae8c000 r--p 00000000 00:1b 93439971 /usr/lib/x86_64-linux-gnu/libabsl_time_zone.so.20220623.0.0
7f877ae7c000-7f877ae8c000 r--p 00000000 00:1b 93439971 /usr/lib/x86_64-linux-gnu/libdbus-1.so.3.34.2rc5
7f877ae7c000-7f877ae8c000 r--p 00000000 00:1b 93439971 /usr/lib/x86_64-linux-gnu/libtoto.so.AAA",
0x7ffe091bf000,
);
assert_eq!(mappings.len(), 9);

let (file_path, file_name, version) = mappings[0]
.get_mapping_effective_path_name_and_version()
.expect("Couldn't get effective name for mapping");
assert_eq!(file_name, "libmozsandbox.so");
assert_eq!(
file_path,
PathBuf::from("/home/alex/bin/firefox/libmozsandbox.so")
);
assert_eq!(version, (0, 0, 0));

let (file_path, file_name, version) = mappings[1]
.get_mapping_effective_path_name_and_version()
.expect("Couldn't get effective name for mapping");
assert_eq!(file_name, "libstdc++.so.6.0.32");
assert_eq!(
file_path,
PathBuf::from("/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.32")
);
assert_eq!(version, (6, 0, 32));

let (file_path, file_name, version) = mappings[2]
.get_mapping_effective_path_name_and_version()
.expect("Couldn't get effective name for mapping");
assert_eq!(file_name, "libcairo-gobject.so.2.11800.0");
assert_eq!(
file_path,
PathBuf::from("/usr/lib/x86_64-linux-gnu/libcairo-gobject.so.2.11800.0")
);
assert_eq!(version, (2, 11800, 0));

let (file_path, file_name, version) = mappings[3]
.get_mapping_effective_path_name_and_version()
.expect("Couldn't get effective name for mapping");
assert_eq!(file_name, "libm.so.6");
assert_eq!(
file_path,
PathBuf::from("/usr/lib/x86_64-linux-gnu/libm.so.6")
);
assert_eq!(version, (6, 0, 0));

let (file_path, file_name, version) = mappings[4]
.get_mapping_effective_path_name_and_version()
.expect("Couldn't get effective name for mapping");
assert_eq!(file_name, "libpthread.so.0");
assert_eq!(
file_path,
PathBuf::from("/usr/lib/x86_64-linux-gnu/libpthread.so.0")
);
assert_eq!(version, (0, 0, 0));

let (file_path, file_name, version) = mappings[5]
.get_mapping_effective_path_name_and_version()
.expect("Couldn't get effective name for mapping");
assert_eq!(file_name, "libgmodule-2.0.so.0.7800.0");
assert_eq!(
file_path,
PathBuf::from("/usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0.7800.0")
);
assert_eq!(version, (0, 7800, 0));

let (file_path, file_name, version) = mappings[6]
.get_mapping_effective_path_name_and_version()
.expect("Couldn't get effective name for mapping");
assert_eq!(file_name, "libabsl_time_zone.so.20220623.0.0");
assert_eq!(
file_path,
PathBuf::from("/usr/lib/x86_64-linux-gnu/libabsl_time_zone.so.20220623")
);
assert_eq!(version, (20220623, 0, 0));

let (file_path, file_name, version) = mappings[7]
.get_mapping_effective_path_name_and_version()
.expect("Couldn't get effective name for mapping");
assert_eq!(file_name, "libdbus-1.so.3.34.2rc5");
assert_eq!(
file_path,
PathBuf::from("/usr/lib/x86_64-linux-gnu/libdbus-1.so.3.34.2rc5")
);
assert_eq!(version, (0, 0, 0));

let (file_path, file_name, version) = mappings[8]
.get_mapping_effective_path_name_and_version()
.expect("Couldn't get effective name for mapping");
assert_eq!(file_name, "libtoto.so.AAA");
assert_eq!(
file_path,
PathBuf::from("/usr/lib/x86_64-linux-gnu/libtoto.so.AAA")
);
assert_eq!(version, (0, 0, 0));
}

#[test]
fn test_whitespaces_in_name() {
let mappings = get_mappings_for(
Expand Down
16 changes: 12 additions & 4 deletions src/linux/sections/mappings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,24 @@ fn fill_raw_module(
sig_section.location()
};

let (file_path, _) = mapping
.get_mapping_effective_path_and_name()
let (file_path, _, (major, minor, release)) = mapping
.get_mapping_effective_path_name_and_version()
.map_err(|e| errors::SectionMappingsError::GetEffectivePathError(mapping.clone(), e))?;
let name_header = write_string_to_location(buffer, file_path.to_string_lossy().as_ref())?;

Ok(MDRawModule {
let mut raw_module = 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()
})
};

raw_module.version_info.signature = format::VS_FFI_SIGNATURE;
raw_module.version_info.struct_version = format::VS_FFI_STRUCVERSION;
raw_module.version_info.file_version_hi = major;
raw_module.version_info.file_version_lo = minor;
raw_module.version_info.product_version_hi = release;

Ok(raw_module)
}

0 comments on commit 66010e0

Please sign in to comment.