|
| 1 | +// Copyright 2019-2024 Tauri Programme within The Commons Conservancy |
| 2 | +// SPDX-License-Identifier: Apache-2.0 |
| 3 | +// SPDX-License-Identifier: MIT |
| 4 | + |
| 5 | +/// Change value of __TAURI_BUNDLE_TYPE static variable to mark which package type it was bundled in |
| 6 | +#[cfg(target_os = "linux")] |
| 7 | +pub fn patch_binary( |
| 8 | + binary_path: &std::path::PathBuf, |
| 9 | + package_type: &crate::PackageType, |
| 10 | +) -> crate::Result<()> { |
| 11 | + let mut file_data = std::fs::read(binary_path).expect("Could not read binary file."); |
| 12 | + |
| 13 | + let elf = match goblin::Object::parse(&file_data)? { |
| 14 | + goblin::Object::Elf(elf) => elf, |
| 15 | + _ => return Err(crate::Error::GenericError("Not an ELF file".to_owned())), |
| 16 | + }; |
| 17 | + |
| 18 | + let offset = find_bundle_type_symbol(elf).ok_or(crate::Error::MissingBundleTypeVar)?; |
| 19 | + let offset = offset as usize; |
| 20 | + if offset + 3 <= file_data.len() { |
| 21 | + let chars = &mut file_data[offset..offset + 3]; |
| 22 | + match package_type { |
| 23 | + crate::PackageType::Deb => chars.copy_from_slice(b"DEB"), |
| 24 | + crate::PackageType::Rpm => chars.copy_from_slice(b"RPM"), |
| 25 | + crate::PackageType::AppImage => chars.copy_from_slice(b"APP"), |
| 26 | + _ => { |
| 27 | + return Err(crate::Error::InvalidPackageType( |
| 28 | + package_type.short_name().to_owned(), |
| 29 | + "linux".to_owned(), |
| 30 | + )) |
| 31 | + } |
| 32 | + } |
| 33 | + |
| 34 | + std::fs::write(binary_path, &file_data) |
| 35 | + .map_err(|error| crate::Error::BinaryWriteError(error.to_string()))?; |
| 36 | + } else { |
| 37 | + return Err(crate::Error::BinaryOffsetOutOfRange); |
| 38 | + } |
| 39 | + |
| 40 | + Ok(()) |
| 41 | +} |
| 42 | + |
| 43 | +/// Find address of a symbol in relocations table |
| 44 | +#[cfg(target_os = "linux")] |
| 45 | +fn find_bundle_type_symbol(elf: goblin::elf::Elf<'_>) -> Option<i64> { |
| 46 | + for sym in elf.syms.iter() { |
| 47 | + if let Some(name) = elf.strtab.get_at(sym.st_name) { |
| 48 | + if name == "__TAURI_BUNDLE_TYPE" { |
| 49 | + for reloc in elf.dynrelas.iter() { |
| 50 | + if reloc.r_offset == sym.st_value { |
| 51 | + return Some(reloc.r_addend.unwrap()); |
| 52 | + } |
| 53 | + } |
| 54 | + } |
| 55 | + } |
| 56 | + } |
| 57 | + |
| 58 | + None |
| 59 | +} |
0 commit comments