Compare commits

...

3 Commits

Author SHA1 Message Date
LagoLunatic 66c879a95d Version 3.6.1 (#328) 2026-01-30 05:40:02 +00:00
rjkiv d53c358d2f automatically match MSVC symbols in anonymous namespaces (#325)
* automatically match MSVC symbols in anonymous namespaces

* tweak logic for detecting anonymous MSVC symbols

* fix package format

* address feedback

* lazylock the regex

* formatting

* use once_cell instead

* formatting

* remove regex
2026-01-30 00:13:10 -05:00
Avery Townsend f24c017545 merge gnu function and data sections (#327) 2026-01-29 16:58:52 -07:00
5 changed files with 35 additions and 10 deletions
Generated
+4 -4
View File
@@ -3491,7 +3491,7 @@ dependencies = [
[[package]]
name = "objdiff-cli"
version = "3.6.0"
version = "3.6.1"
dependencies = [
"anyhow",
"argp",
@@ -3514,7 +3514,7 @@ dependencies = [
[[package]]
name = "objdiff-core"
version = "3.6.0"
version = "3.6.1"
dependencies = [
"anyhow",
"arm-attr",
@@ -3570,7 +3570,7 @@ dependencies = [
[[package]]
name = "objdiff-gui"
version = "3.6.0"
version = "3.6.1"
dependencies = [
"anyhow",
"argp",
@@ -3608,7 +3608,7 @@ dependencies = [
[[package]]
name = "objdiff-wasm"
version = "3.6.0"
version = "3.6.1"
dependencies = [
"log",
"objdiff-core",
+1 -1
View File
@@ -14,7 +14,7 @@ default-members = [
resolver = "3"
[workspace.package]
version = "3.6.0"
version = "3.6.1"
authors = ["Luke Street <luke@street.dev>"]
edition = "2024"
license = "MIT OR Apache-2.0"
+27 -2
View File
@@ -40,6 +40,7 @@ fn map_section_kind(section: &object::Section) -> SectionKind {
/// e.g. symbol$1234 and symbol$2345 will both be replaced with symbol$0000 internally.
fn get_normalized_symbol_name(name: &str) -> Option<String> {
const DUMMY_UNIQUE_ID: &str = "0000";
const DUMMY_UNIQUE_MSVC_ID: &str = "00000000";
if let Some((prefix, suffix)) = name.split_once("@class$")
&& let Some(idx) = suffix.chars().position(|c| !c.is_numeric())
&& idx > 0
@@ -59,6 +60,26 @@ fn get_normalized_symbol_name(name: &str) -> Option<String> {
{
// Match GCC symbol.1234 against symbol.2345
Some(format!("{prefix}.{DUMMY_UNIQUE_ID}"))
} else if name.starts_with('?') {
// Match MSVC anonymous class symbol names, ignoring the unique ID.
// e.g. ?CheckContextOr@?A0x24773155@@YA_NPBVDataArray@@@Z
// and: ?CheckContextOr@?A0xddf6240c@@YA_NPBVDataArray@@@Z
let mut name_str = String::from(name);
let anon_indices: Vec<usize> = name_str.match_indices("?A0x").map(|(idx, _)| idx).collect();
if !anon_indices.is_empty() {
for idx in anon_indices {
// the str sequence we're looking for is: ?A0xXXXXXXXX@@
if u32::from_str_radix(&name_str[idx + 4..idx + 12], 16).is_ok()
&& &name_str[idx + 12..idx + 14] == "@@"
{
// if the two above checks passed, we're good to replace the hash
name_str.replace_range(idx + 4..idx + 12, DUMMY_UNIQUE_MSVC_ID);
}
}
Some(name_str)
} else {
None
}
} else {
None
}
@@ -874,8 +895,12 @@ fn combine_sections(
let mut data_sections = BTreeMap::<String, Vec<usize>>::new();
let mut text_sections = BTreeMap::<String, Vec<usize>>::new();
for (i, section) in sections.iter().enumerate() {
let base_name =
if let Some(i) = section.name.rfind('$') { &section.name[..i] } else { &section.name };
let base_name = section
.name
.get(1..)
.and_then(|s| s.rfind(['$', '.']))
.and_then(|i| section.name.get(..i + 1))
.unwrap_or(&section.name);
match section.kind {
SectionKind::Data | SectionKind::Bss => {
data_sections.entry(base_name.to_string()).or_default().push(i);
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "objdiff-wasm",
"version": "3.6.0",
"version": "3.6.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "objdiff-wasm",
"version": "3.6.0",
"version": "3.6.1",
"license": "MIT OR Apache-2.0",
"devDependencies": {
"@biomejs/biome": "^1.9.3",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "objdiff-wasm",
"version": "3.6.0",
"version": "3.6.1",
"description": "A local diffing tool for decompilation projects.",
"author": {
"name": "Luke Street",