Skip to content

Commit 741d93e

Browse files
authored
Add symbol mapping feature (#118)
This allows users to "map" (or "link") symbols with different names so that they can be compared without having to update either the target or base objects. Symbol mappings are persisted in objdiff.json, so generators will need to ensure that they're preserved when updating. (Example: encounter/dtk-template@d1334bb) Resolves #117
1 parent 603dbd6 commit 741d93e

26 files changed

+2257
-926
lines changed

Cargo.lock

Lines changed: 13 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ strip = "debuginfo"
1313
codegen-units = 1
1414

1515
[workspace.package]
16-
version = "2.2.2"
16+
version = "2.3.0"
1717
authors = ["Luke Street <luke@street.dev>"]
1818
edition = "2021"
1919
license = "MIT OR Apache-2.0"

config.schema.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,13 @@
133133
},
134134
"metadata": {
135135
"ref": "#/$defs/metadata"
136+
},
137+
"symbol_mappings": {
138+
"type": "object",
139+
"description": "Manual symbol mappings from target to base.",
140+
"additionalProperties": {
141+
"type": "string"
142+
}
136143
}
137144
}
138145
},

objdiff-cli/src/cmd/diff.rs

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -102,34 +102,46 @@ pub fn run(args: Args) -> Result<()> {
102102
let unit_path =
103103
PathBuf::from_str(u).ok().and_then(|p| fs::canonicalize(p).ok());
104104

105-
let Some(object) = project_config.objects.iter_mut().find_map(|obj| {
106-
if obj.name.as_deref() == Some(u) {
107-
resolve_paths(obj);
108-
return Some(obj);
109-
}
105+
let Some(object) = project_config
106+
.units
107+
.as_deref_mut()
108+
.unwrap_or_default()
109+
.iter_mut()
110+
.find_map(|obj| {
111+
if obj.name.as_deref() == Some(u) {
112+
resolve_paths(obj);
113+
return Some(obj);
114+
}
110115

111-
let up = unit_path.as_deref()?;
116+
let up = unit_path.as_deref()?;
112117

113-
resolve_paths(obj);
118+
resolve_paths(obj);
114119

115-
if [&obj.base_path, &obj.target_path]
116-
.into_iter()
117-
.filter_map(|p| p.as_ref().and_then(|p| p.canonicalize().ok()))
118-
.any(|p| p == up)
119-
{
120-
return Some(obj);
121-
}
120+
if [&obj.base_path, &obj.target_path]
121+
.into_iter()
122+
.filter_map(|p| p.as_ref().and_then(|p| p.canonicalize().ok()))
123+
.any(|p| p == up)
124+
{
125+
return Some(obj);
126+
}
122127

123-
None
124-
}) else {
128+
None
129+
})
130+
else {
125131
bail!("Unit not found: {}", u)
126132
};
127133

128134
object
129135
} else if let Some(symbol_name) = &args.symbol {
130136
let mut idx = None;
131137
let mut count = 0usize;
132-
for (i, obj) in project_config.objects.iter_mut().enumerate() {
138+
for (i, obj) in project_config
139+
.units
140+
.as_deref_mut()
141+
.unwrap_or_default()
142+
.iter_mut()
143+
.enumerate()
144+
{
133145
resolve_paths(obj);
134146

135147
if obj
@@ -148,7 +160,7 @@ pub fn run(args: Args) -> Result<()> {
148160
}
149161
match (count, idx) {
150162
(0, None) => bail!("Symbol not found: {}", symbol_name),
151-
(1, Some(i)) => &mut project_config.objects[i],
163+
(1, Some(i)) => &mut project_config.units_mut()[i],
152164
(2.., Some(_)) => bail!(
153165
"Multiple instances of {} were found, try specifying a unit",
154166
symbol_name
@@ -303,7 +315,7 @@ fn find_function(obj: &ObjInfo, name: &str) -> Option<SymbolRef> {
303315
None
304316
}
305317

306-
#[allow(dead_code)]
318+
#[expect(dead_code)]
307319
struct FunctionDiffUi {
308320
relax_reloc_diffs: bool,
309321
left_highlight: HighlightKind,
@@ -758,7 +770,7 @@ impl FunctionDiffUi {
758770
self.scroll_y += self.per_page / if half { 2 } else { 1 };
759771
}
760772

761-
#[allow(clippy::too_many_arguments)]
773+
#[expect(clippy::too_many_arguments)]
762774
fn print_sym(
763775
&self,
764776
out: &mut Text<'static>,

objdiff-cli/src/cmd/report.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ fn generate(args: GenerateArgs) -> Result<()> {
9494
};
9595
info!(
9696
"Generating report for {} units (using {} threads)",
97-
project.objects.len(),
97+
project.units().len(),
9898
if args.deduplicate { 1 } else { rayon::current_num_threads() }
9999
);
100100

@@ -103,7 +103,7 @@ fn generate(args: GenerateArgs) -> Result<()> {
103103
let mut existing_functions: HashSet<String> = HashSet::new();
104104
if args.deduplicate {
105105
// If deduplicating, we need to run single-threaded
106-
for object in &mut project.objects {
106+
for object in project.units.as_deref_mut().unwrap_or_default() {
107107
if let Some(unit) = report_object(
108108
object,
109109
project_dir,
@@ -116,7 +116,9 @@ fn generate(args: GenerateArgs) -> Result<()> {
116116
}
117117
} else {
118118
let vec = project
119-
.objects
119+
.units
120+
.as_deref_mut()
121+
.unwrap_or_default()
120122
.par_iter_mut()
121123
.map(|object| {
122124
report_object(
@@ -132,7 +134,7 @@ fn generate(args: GenerateArgs) -> Result<()> {
132134
}
133135
let measures = units.iter().flat_map(|u| u.measures.into_iter()).collect();
134136
let mut categories = Vec::new();
135-
for category in &project.progress_categories {
137+
for category in project.progress_categories() {
136138
categories.push(ReportCategory {
137139
id: category.id.clone(),
138140
name: category.name.clone(),

objdiff-core/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ crate-type = ["cdylib", "rlib"]
1717

1818
[features]
1919
all = ["config", "dwarf", "mips", "ppc", "x86", "arm", "bindings"]
20-
any-arch = [] # Implicit, used to check if any arch is enabled
21-
config = ["globset", "semver", "serde_json", "serde_yaml"]
20+
any-arch = ["bimap"] # Implicit, used to check if any arch is enabled
21+
config = ["bimap", "globset", "semver", "serde_json", "serde_yaml"]
2222
dwarf = ["gimli"]
2323
mips = ["any-arch", "rabbitizer"]
2424
ppc = ["any-arch", "cwdemangle", "cwextab", "ppc750cl"]
@@ -32,6 +32,7 @@ features = ["all"]
3232

3333
[dependencies]
3434
anyhow = "1.0"
35+
bimap = { version = "0.6", features = ["serde"], optional = true }
3536
byteorder = "1.5"
3637
filetime = "0.2"
3738
flagset = "0.4"

0 commit comments

Comments
 (0)