Better COFF String Detection and Big Endian Wide Strings (#321)

* Better COFF and Big Endian Strings

* Cargo Check and Format Fixes

* Rework DataType::String in display_literals

---------

Co-authored-by: Luke Street <luke@street.dev>
This commit is contained in:
Haydn Trigg
2026-01-25 13:53:06 +10:30
committed by GitHub
parent 926dd06ce9
commit 3f82781808
2 changed files with 33 additions and 18 deletions
+30 -17
View File
@@ -174,23 +174,36 @@ impl DataType {
strs.push((format!("{bytes:#?}"), None, None));
}
DataType::String => {
if let Some(nul_idx) = bytes.iter().position(|&c| c == b'\0') {
let str_bytes = &bytes[..nul_idx];
// Special case to display (ASCII) as the label for ASCII-only strings.
let (cow, _, had_errors) = encoding_rs::UTF_8.decode(str_bytes);
if !had_errors && cow.is_ascii() {
let string = format!("{cow}");
let copy_string = escape_special_ascii_characters(string.clone());
strs.push((string, Some("ASCII".into()), Some(copy_string)));
// Special case to display (ASCII) as the label for ASCII-only strings.
let mut is_ascii = false;
if bytes.is_ascii()
&& let Ok(str) = str::from_utf8(bytes)
{
let trimmed = str.trim_end_matches('\0');
if !trimmed.is_empty() {
let copy_string = escape_special_ascii_characters(trimmed);
strs.push((trimmed.to_string(), Some("ASCII".into()), Some(copy_string)));
is_ascii = true;
}
for (encoding, encoding_name) in SUPPORTED_ENCODINGS {
let (cow, _, had_errors) = encoding.decode(str_bytes);
// Avoid showing ASCII-only strings more than once if the encoding is ASCII-compatible.
if !had_errors && (!encoding.is_ascii_compatible() || !cow.is_ascii()) {
let string = format!("{cow}");
let copy_string = escape_special_ascii_characters(string.clone());
strs.push((string, Some(encoding_name.into()), Some(copy_string)));
}
}
for (encoding, encoding_name) in SUPPORTED_ENCODINGS {
// Avoid showing ASCII-only strings more than once if the encoding is ASCII-compatible.
if is_ascii && encoding.is_ascii_compatible() {
continue;
}
let (cow, _, had_errors) = encoding.decode(bytes);
if had_errors {
continue;
}
let trimmed = cow.trim_end_matches('\0');
if !trimmed.is_empty() {
let copy_string = escape_special_ascii_characters(trimmed);
strs.push((
trimmed.to_string(),
Some(encoding_name.into()),
Some(copy_string),
));
}
}
}
@@ -508,7 +521,7 @@ pub struct RelocationOverride {
/// Escape ASCII characters such as \n or \t, but not Unicode characters such as \u{3000}.
/// Suitable for copying to clipboard.
fn escape_special_ascii_characters(value: String) -> String {
fn escape_special_ascii_characters(value: &str) -> String {
let mut escaped = String::new();
escaped.push('"');
for c in value.chars() {
+3 -1
View File
@@ -361,7 +361,9 @@ impl Arch for ArchPpc {
}
fn guess_data_type(&self, resolved: ResolvedInstructionRef, bytes: &[u8]) -> Option<DataType> {
if resolved.relocation.is_some_and(|r| r.symbol.name.starts_with("@stringBase")) {
if resolved.relocation.is_some_and(|r| {
r.symbol.name.starts_with("@stringBase") || r.symbol.name.starts_with("$SG")
}) {
// Pooled string.
return Some(DataType::String);
}