diff --git a/Cargo.lock b/Cargo.lock index d084c223..5c45a4f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1427,7 +1427,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3337,6 +3337,7 @@ dependencies = [ "cpp_demangle", "cwdemangle", "cwextab", + "encoding_rs", "filetime", "flagset", "gimli", @@ -3458,9 +3459,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.71" +version = "0.10.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" +checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" dependencies = [ "bitflags 2.9.0", "cfg-if", @@ -3490,9 +3491,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.106" +version = "0.9.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" +checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" dependencies = [ "cc", "libc", @@ -3921,7 +3922,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4353,7 +4354,7 @@ dependencies = [ "errno 0.3.10", "libc", "linux-raw-sys 0.4.15", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4366,7 +4367,7 @@ dependencies = [ "errno 0.3.10", "libc", "linux-raw-sys 0.9.3", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4973,7 +4974,7 @@ dependencies = [ "getrandom 0.3.2", "once_cell", "rustix 1.0.5", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5131,9 +5132,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.44.1" +version = "1.44.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" +checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" dependencies = [ "backtrace", "bytes", diff --git a/objdiff-core/Cargo.toml b/objdiff-core/Cargo.toml index e78816b0..919eefa4 100644 --- a/objdiff-core/Cargo.toml +++ b/objdiff-core/Cargo.toml @@ -167,6 +167,7 @@ notify-debouncer-full = { version = "0.5.0", optional = true } shell-escape = { version = "0.1", optional = true } tempfile = { version = "3.19", optional = true } time = { version = "0.3", optional = true } +encoding_rs = "0.8.35" [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", optional = true } diff --git a/objdiff-core/src/arch/mod.rs b/objdiff-core/src/arch/mod.rs index f2cfa90e..00d37d14 100644 --- a/objdiff-core/src/arch/mod.rs +++ b/objdiff-core/src/arch/mod.rs @@ -2,6 +2,7 @@ use alloc::{borrow::Cow, boxed::Box, format, string::String, vec::Vec}; use core::{ffi::CStr, fmt, fmt::Debug}; use anyhow::{Result, bail}; +use encoding_rs::SHIFT_JIS; use object::Endian as _; use crate::{ @@ -57,13 +58,18 @@ impl fmt::Display for DataType { impl DataType { pub fn display_labels(&self, endian: object::Endianness, bytes: &[u8]) -> Vec { let mut strs = Vec::new(); - for literal in self.display_literals(endian, bytes) { - strs.push(format!("{}: {}", self, literal)) + for (literal, label_override) in self.display_literals(endian, bytes) { + let label = label_override.unwrap_or_else(|| format!("{}", self)); + strs.push(format!("{}: {}", label, literal)) } strs } - pub fn display_literals(&self, endian: object::Endianness, bytes: &[u8]) -> Vec { + pub fn display_literals( + &self, + endian: object::Endianness, + bytes: &[u8], + ) -> Vec<(String, Option)> { let mut strs = Vec::new(); if self.required_len().is_some_and(|l| bytes.len() < l) { log::warn!( @@ -87,56 +93,72 @@ impl DataType { match self { DataType::Int8 => { let i = i8::from_ne_bytes(bytes.try_into().unwrap()); - strs.push(format!("{:#x}", i)); + strs.push((format!("{:#x}", i), None)); if i < 0 { - strs.push(format!("{:#x}", ReallySigned(i))); + strs.push((format!("{:#x}", ReallySigned(i)), None)); } } DataType::Int16 => { let i = endian.read_i16_bytes(bytes.try_into().unwrap()); - strs.push(format!("{:#x}", i)); + strs.push((format!("{:#x}", i), None)); if i < 0 { - strs.push(format!("{:#x}", ReallySigned(i))); + strs.push((format!("{:#x}", ReallySigned(i)), None)); } } DataType::Int32 => { let i = endian.read_i32_bytes(bytes.try_into().unwrap()); - strs.push(format!("{:#x}", i)); + strs.push((format!("{:#x}", i), None)); if i < 0 { - strs.push(format!("{:#x}", ReallySigned(i))); + strs.push((format!("{:#x}", ReallySigned(i)), None)); } } DataType::Int64 => { let i = endian.read_i64_bytes(bytes.try_into().unwrap()); - strs.push(format!("{:#x}", i)); + strs.push((format!("{:#x}", i), None)); if i < 0 { - strs.push(format!("{:#x}", ReallySigned(i))); + strs.push((format!("{:#x}", ReallySigned(i)), None)); } } DataType::Float => { let bytes: [u8; 4] = bytes.try_into().unwrap(); - strs.push(format!("{:?}f", match endian { - object::Endianness::Little => f32::from_le_bytes(bytes), - object::Endianness::Big => f32::from_be_bytes(bytes), - })); + strs.push(( + format!("{:?}f", match endian { + object::Endianness::Little => f32::from_le_bytes(bytes), + object::Endianness::Big => f32::from_be_bytes(bytes), + }), + None, + )); } DataType::Double => { let bytes: [u8; 8] = bytes.try_into().unwrap(); - strs.push(format!("{:?}", match endian { - object::Endianness::Little => f64::from_le_bytes(bytes), - object::Endianness::Big => f64::from_be_bytes(bytes), - })); + strs.push(( + format!("{:?}", match endian { + object::Endianness::Little => f64::from_le_bytes(bytes), + object::Endianness::Big => f64::from_be_bytes(bytes), + }), + None, + )); } DataType::Bytes => { - strs.push(format!("{:#?}", bytes)); + strs.push((format!("{:#?}", bytes), None)); } DataType::String => { if let Ok(cstr) = CStr::from_bytes_until_nul(bytes) { - strs.push(format!("{:?}", cstr)); + strs.push((format!("{:?}", cstr), None)); + } + if let Some(nul_idx) = bytes.iter().position(|&c| c == b'\0') { + let (cow, _, had_errors) = SHIFT_JIS.decode(&bytes[..nul_idx]); + if !had_errors { + let str = format!("{:?}", cow); + // Only add the Shift JIS string if it's different from the ASCII string. + if !strs.iter().any(|x| x.0 == str) { + strs.push((str, Some("Shift JIS".into()))); + } + } } } } diff --git a/objdiff-core/src/diff/display.rs b/objdiff-core/src/diff/display.rs index 193ae683..ead3f658 100644 --- a/objdiff-core/src/diff/display.rs +++ b/objdiff-core/src/diff/display.rs @@ -444,8 +444,8 @@ pub fn relocation_context( let literals = display_ins_data_literals(obj, ins); if !literals.is_empty() { out.push(ContextItem::Separator); - for literal in literals { - out.push(ContextItem::Copy { value: literal, label: None }); + for (literal, label_override) in literals { + out.push(ContextItem::Copy { value: literal, label: label_override }); } } } @@ -568,9 +568,9 @@ pub fn instruction_hover( let literals = display_ins_data_literals(obj, resolved); if !literals.is_empty() { out.push(HoverItem::Separator); - for literal in literals { + for (literal, label_override) in literals { out.push(HoverItem::Text { - label: format!("{}", ty), + label: label_override.unwrap_or_else(|| format!("{}", ty)), value: literal, color: HoverItemColor::Normal, }); @@ -763,7 +763,10 @@ pub fn display_ins_data_labels(obj: &Object, resolved: ResolvedInstructionRef) - .unwrap_or_default() } -pub fn display_ins_data_literals(obj: &Object, resolved: ResolvedInstructionRef) -> Vec { +pub fn display_ins_data_literals( + obj: &Object, + resolved: ResolvedInstructionRef, +) -> Vec<(String, Option)> { let Some(reloc) = resolved.relocation else { return Vec::new(); };