mirror of
https://github.com/encounter/objdiff.git
synced 2025-12-15 08:06:25 +00:00
Compare commits
7 Commits
v3.0.0-alp
...
v3.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
| fa4a6cadbb | |||
| 799971d54e | |||
| 8eef37e8df | |||
| 5f36916087 | |||
| ee667a2dde | |||
|
|
cf5fc54cfa | ||
| 1cdfa1e857 |
13
Cargo.lock
generated
13
Cargo.lock
generated
@@ -3268,7 +3268,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objdiff-cli"
|
name = "objdiff-cli"
|
||||||
version = "3.0.0-alpha.3"
|
version = "3.0.0-beta.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"argp",
|
"argp",
|
||||||
@@ -3291,7 +3291,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objdiff-core"
|
name = "objdiff-core"
|
||||||
version = "3.0.0-alpha.3"
|
version = "3.0.0-beta.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"arm-attr",
|
"arm-attr",
|
||||||
@@ -3344,13 +3344,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objdiff-gui"
|
name = "objdiff-gui"
|
||||||
version = "3.0.0-alpha.3"
|
version = "3.0.0-beta.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"const_format",
|
"const_format",
|
||||||
"cwdemangle",
|
"cwdemangle",
|
||||||
"cwextab",
|
|
||||||
"dirs 6.0.0",
|
"dirs 6.0.0",
|
||||||
"eframe",
|
"eframe",
|
||||||
"egui",
|
"egui",
|
||||||
@@ -3370,8 +3369,6 @@ dependencies = [
|
|||||||
"rlwinmdec",
|
"rlwinmdec",
|
||||||
"ron",
|
"ron",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
|
||||||
"shell-escape",
|
|
||||||
"tauri-winres",
|
"tauri-winres",
|
||||||
"time",
|
"time",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
@@ -3383,7 +3380,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objdiff-wasm"
|
name = "objdiff-wasm"
|
||||||
version = "3.0.0-alpha.3"
|
version = "3.0.0-beta.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"objdiff-core",
|
"objdiff-core",
|
||||||
@@ -3897,7 +3894,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "rabbitizer"
|
name = "rabbitizer"
|
||||||
version = "2.0.0-dev0"
|
version = "2.0.0-dev0"
|
||||||
source = "git+https://github.com/Decompollaborate/rabbitizer.git?branch=🦀#706fd145b788ec3d068d55904dd112c7989e0412"
|
source = "git+https://github.com/Decompollaborate/rabbitizer.git?branch=🦀#06dc8b6c826c3d60e112d4c2cd70aa54e308be12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.0",
|
"bitflags 2.9.0",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ members = [
|
|||||||
"objdiff-gui",
|
"objdiff-gui",
|
||||||
"objdiff-wasm",
|
"objdiff-wasm",
|
||||||
]
|
]
|
||||||
resolver = "2"
|
resolver = "3"
|
||||||
|
|
||||||
[profile.release-lto]
|
[profile.release-lto]
|
||||||
inherits = "release"
|
inherits = "release"
|
||||||
@@ -14,9 +14,9 @@ strip = "debuginfo"
|
|||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "3.0.0-alpha.3"
|
version = "3.0.0-beta.1"
|
||||||
authors = ["Luke Street <luke@street.dev>"]
|
authors = ["Luke Street <luke@street.dev>"]
|
||||||
edition = "2021"
|
edition = "2024"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
repository = "https://github.com/encounter/objdiff"
|
repository = "https://github.com/encounter/objdiff"
|
||||||
rust-version = "1.82"
|
rust-version = "1.85"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
//! For now, this only adds a --version/-V option which causes early-exit.
|
//! For now, this only adds a --version/-V option which causes early-exit.
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
|
|
||||||
use argp::{parser::ParseGlobalOptions, EarlyExit, FromArgs, TopLevelCommand};
|
use argp::{EarlyExit, FromArgs, TopLevelCommand, parser::ParseGlobalOptions};
|
||||||
|
|
||||||
struct ArgsOrVersion<T>(T)
|
struct ArgsOrVersion<T>(T)
|
||||||
where T: FromArgs;
|
where T: FromArgs;
|
||||||
|
|||||||
@@ -3,40 +3,39 @@ use std::{
|
|||||||
mem,
|
mem,
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicBool, Ordering},
|
|
||||||
Arc,
|
Arc,
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
},
|
},
|
||||||
task::{Wake, Waker},
|
task::{Wake, Waker},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{anyhow, bail, Context, Result};
|
use anyhow::{Context, Result, anyhow, bail};
|
||||||
use argp::FromArgs;
|
use argp::FromArgs;
|
||||||
use crossterm::{
|
use crossterm::{
|
||||||
event,
|
event,
|
||||||
event::{DisableMouseCapture, EnableMouseCapture},
|
event::{DisableMouseCapture, EnableMouseCapture},
|
||||||
terminal::{
|
terminal::{
|
||||||
disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen, SetTitle,
|
EnterAlternateScreen, LeaveAlternateScreen, SetTitle, disable_raw_mode, enable_raw_mode,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use objdiff_core::{
|
use objdiff_core::{
|
||||||
bindings::diff::DiffResult,
|
bindings::diff::DiffResult,
|
||||||
build::{
|
build::{
|
||||||
watcher::{create_watcher, Watcher},
|
|
||||||
BuildConfig,
|
BuildConfig,
|
||||||
|
watcher::{Watcher, create_watcher},
|
||||||
},
|
},
|
||||||
config::{
|
config::{
|
||||||
build_globset,
|
ProjectConfig, ProjectObject, ProjectObjectMetadata, build_globset,
|
||||||
path::{check_path_buf, platform_path, platform_path_serde_option},
|
path::{check_path_buf, platform_path, platform_path_serde_option},
|
||||||
ProjectConfig, ProjectObject, ProjectObjectMetadata,
|
|
||||||
},
|
},
|
||||||
diff::{
|
diff::{
|
||||||
self, ConfigEnum, ConfigPropertyId, ConfigPropertyKind, DiffObjConfig, MappingConfig,
|
self, ConfigEnum, ConfigPropertyId, ConfigPropertyKind, DiffObjConfig, MappingConfig,
|
||||||
ObjectDiff,
|
ObjectDiff,
|
||||||
},
|
},
|
||||||
jobs::{
|
jobs::{
|
||||||
objdiff::{start_build, ObjDiffConfig},
|
|
||||||
Job, JobQueue, JobResult,
|
Job, JobQueue, JobResult,
|
||||||
|
objdiff::{ObjDiffConfig, start_build},
|
||||||
},
|
},
|
||||||
obj::{self, Object},
|
obj::{self, Object},
|
||||||
};
|
};
|
||||||
@@ -45,10 +44,10 @@ use typed_path::{Utf8PlatformPath, Utf8PlatformPathBuf};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
util::{
|
util::{
|
||||||
output::{write_output, OutputFormat},
|
output::{OutputFormat, write_output},
|
||||||
term::crossterm_panic_handler,
|
term::crossterm_panic_handler,
|
||||||
},
|
},
|
||||||
views::{function_diff::FunctionDiffUi, EventControlFlow, EventResult, UiView},
|
views::{EventControlFlow, EventResult, UiView, function_diff::FunctionDiffUi},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(FromArgs, PartialEq, Debug)]
|
#[derive(FromArgs, PartialEq, Debug)]
|
||||||
@@ -426,15 +425,17 @@ fn run_interactive(
|
|||||||
let mut result = EventResult { redraw: true, ..Default::default() };
|
let mut result = EventResult { redraw: true, ..Default::default() };
|
||||||
'outer: loop {
|
'outer: loop {
|
||||||
if result.redraw {
|
if result.redraw {
|
||||||
terminal.draw(|f| loop {
|
terminal.draw(|f| {
|
||||||
result.redraw = false;
|
loop {
|
||||||
view.draw(&state, f, &mut result);
|
result.redraw = false;
|
||||||
result.click_xy = None;
|
view.draw(&state, f, &mut result);
|
||||||
if !result.redraw {
|
result.click_xy = None;
|
||||||
break;
|
if !result.redraw {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Clear buffer on redraw
|
||||||
|
f.buffer_mut().reset();
|
||||||
}
|
}
|
||||||
// Clear buffer on redraw
|
|
||||||
f.buffer_mut().reset();
|
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
loop {
|
loop {
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
use std::{collections::HashSet, fs::File, io::Read, time::Instant};
|
use std::{collections::HashSet, fs::File, io::Read, time::Instant};
|
||||||
|
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{Context, Result, bail};
|
||||||
use argp::FromArgs;
|
use argp::FromArgs;
|
||||||
use objdiff_core::{
|
use objdiff_core::{
|
||||||
bindings::report::{
|
bindings::report::{
|
||||||
ChangeItem, ChangeItemInfo, ChangeUnit, Changes, ChangesInput, Measures, Report,
|
ChangeItem, ChangeItemInfo, ChangeUnit, Changes, ChangesInput, Measures, REPORT_VERSION,
|
||||||
ReportCategory, ReportItem, ReportItemMetadata, ReportUnit, ReportUnitMetadata,
|
Report, ReportCategory, ReportItem, ReportItemMetadata, ReportUnit, ReportUnitMetadata,
|
||||||
REPORT_VERSION,
|
|
||||||
},
|
},
|
||||||
config::path::platform_path,
|
config::path::platform_path,
|
||||||
diff, obj,
|
diff, obj,
|
||||||
@@ -19,7 +18,7 @@ use typed_path::{Utf8PlatformPath, Utf8PlatformPathBuf};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cmd::diff::ObjectConfig,
|
cmd::diff::ObjectConfig,
|
||||||
util::output::{write_output, OutputFormat},
|
util::output::{OutputFormat, write_output},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(FromArgs, PartialEq, Debug)]
|
#[derive(FromArgs, PartialEq, Debug)]
|
||||||
@@ -206,11 +205,7 @@ fn report_object(
|
|||||||
let section_match_percent = section_diff.match_percent.unwrap_or_else(|| {
|
let section_match_percent = section_diff.match_percent.unwrap_or_else(|| {
|
||||||
// Support cases where we don't have a target object,
|
// Support cases where we don't have a target object,
|
||||||
// assume complete means 100% match
|
// assume complete means 100% match
|
||||||
if object.complete.unwrap_or(false) {
|
if object.complete.unwrap_or(false) { 100.0 } else { 0.0 }
|
||||||
100.0
|
|
||||||
} else {
|
|
||||||
0.0
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
sections.push(ReportItem {
|
sections.push(ReportItem {
|
||||||
name: section.name.clone(),
|
name: section.name.clone(),
|
||||||
@@ -251,11 +246,7 @@ fn report_object(
|
|||||||
let match_percent = symbol_diff.match_percent.unwrap_or_else(|| {
|
let match_percent = symbol_diff.match_percent.unwrap_or_else(|| {
|
||||||
// Support cases where we don't have a target object,
|
// Support cases where we don't have a target object,
|
||||||
// assume complete means 100% match
|
// assume complete means 100% match
|
||||||
if object.complete.unwrap_or(false) {
|
if object.complete.unwrap_or(false) { 100.0 } else { 0.0 }
|
||||||
100.0
|
|
||||||
} else {
|
|
||||||
0.0
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
measures.fuzzy_match_percent += match_percent * symbol.size as f32;
|
measures.fuzzy_match_percent += match_percent * symbol.size as f32;
|
||||||
measures.total_code += symbol.size;
|
measures.total_code += symbol.size;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use anyhow::{Error, Result};
|
|||||||
use argp::{FromArgValue, FromArgs};
|
use argp::{FromArgValue, FromArgs};
|
||||||
use enable_ansi_support::enable_ansi_support;
|
use enable_ansi_support::enable_ansi_support;
|
||||||
use supports_color::Stream;
|
use supports_color::Stream;
|
||||||
use tracing_subscriber::{filter::LevelFilter, EnvFilter};
|
use tracing_subscriber::{EnvFilter, filter::LevelFilter};
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
||||||
enum LogLevel {
|
enum LogLevel {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use std::{
|
|||||||
path::Path,
|
path::Path,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{Context, Result, bail};
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::{io::stdout, panic};
|
|||||||
use crossterm::{
|
use crossterm::{
|
||||||
cursor::Show,
|
cursor::Show,
|
||||||
event::DisableMouseCapture,
|
event::DisableMouseCapture,
|
||||||
terminal::{disable_raw_mode, LeaveAlternateScreen},
|
terminal::{LeaveAlternateScreen, disable_raw_mode},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn crossterm_panic_handler() {
|
pub fn crossterm_panic_handler() {
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{Result, bail};
|
||||||
use crossterm::event::{Event, KeyCode, KeyEventKind, KeyModifiers, MouseButton, MouseEventKind};
|
use crossterm::event::{Event, KeyCode, KeyEventKind, KeyModifiers, MouseButton, MouseEventKind};
|
||||||
use objdiff_core::{
|
use objdiff_core::{
|
||||||
diff::{
|
diff::{
|
||||||
display::{display_row, DiffText, DiffTextColor, HighlightKind},
|
|
||||||
DiffObjConfig, FunctionRelocDiffs, InstructionDiffKind, ObjectDiff, SymbolDiff,
|
DiffObjConfig, FunctionRelocDiffs, InstructionDiffKind, ObjectDiff, SymbolDiff,
|
||||||
|
display::{DiffText, DiffTextColor, HighlightKind, display_row},
|
||||||
},
|
},
|
||||||
obj::Object,
|
obj::Object,
|
||||||
};
|
};
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
|
Frame,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
widgets::{Block, Borders, Clear, Paragraph, Scrollbar, ScrollbarOrientation, ScrollbarState},
|
widgets::{Block, Borders, Clear, Paragraph, Scrollbar, ScrollbarOrientation, ScrollbarState},
|
||||||
Frame,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{EventControlFlow, EventResult, UiView};
|
use super::{EventControlFlow, EventResult, UiView};
|
||||||
|
|||||||
@@ -194,6 +194,13 @@
|
|||||||
"name": "Register '$' prefix",
|
"name": "Register '$' prefix",
|
||||||
"description": "Display MIPS register names with a '$' prefix."
|
"description": "Display MIPS register names with a '$' prefix."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "ppc.calculatePoolRelocations",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"name": "Calculate pooled data references",
|
||||||
|
"description": "Display pooled data references in functions as fake relocations."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "x86.formatter",
|
"id": "x86.formatter",
|
||||||
"type": "choice",
|
"type": "choice",
|
||||||
@@ -253,6 +260,13 @@
|
|||||||
"mips.registerPrefix"
|
"mips.registerPrefix"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "ppc",
|
||||||
|
"name": "PowerPC",
|
||||||
|
"properties": [
|
||||||
|
"ppc.calculatePoolRelocations"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "x86",
|
"id": "x86",
|
||||||
"name": "x86",
|
"name": "x86",
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ use alloc::{
|
|||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{Result, bail};
|
||||||
use arm_attr::{enums::CpuArch, tag::Tag, BuildAttrs};
|
use arm_attr::{BuildAttrs, enums::CpuArch, tag::Tag};
|
||||||
use object::{elf, Endian as _, Object as _, ObjectSection as _, ObjectSymbol as _};
|
use object::{Endian as _, Object as _, ObjectSection as _, ObjectSymbol as _, elf};
|
||||||
use unarm::{args, arm, thumb};
|
use unarm::{args, arm, thumb};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::Arch,
|
arch::Arch,
|
||||||
diff::{display::InstructionPart, ArmArchVersion, ArmR9Usage, DiffObjConfig},
|
diff::{ArmArchVersion, ArmR9Usage, DiffObjConfig, display::InstructionPart},
|
||||||
obj::{
|
obj::{
|
||||||
InstructionRef, RelocationFlags, ResolvedInstructionRef, ResolvedRelocation,
|
InstructionRef, RelocationFlags, ResolvedInstructionRef, ResolvedRelocation,
|
||||||
ScannedInstruction, SymbolFlag, SymbolFlagSet, SymbolKind,
|
ScannedInstruction, SymbolFlag, SymbolFlagSet, SymbolKind,
|
||||||
@@ -58,11 +58,7 @@ impl ArchArm {
|
|||||||
}
|
}
|
||||||
// Only checking first CpuArch tag. Others may exist, but that's very unlikely.
|
// Only checking first CpuArch tag. Others may exist, but that's very unlikely.
|
||||||
let cpu_arch = subsection.into_public_tag_iter()?.find_map(|(_, tag)| {
|
let cpu_arch = subsection.into_public_tag_iter()?.find_map(|(_, tag)| {
|
||||||
if let Tag::CpuArch(cpu_arch) = tag {
|
if let Tag::CpuArch(cpu_arch) = tag { Some(cpu_arch) } else { None }
|
||||||
Some(cpu_arch)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
match cpu_arch {
|
match cpu_arch {
|
||||||
Some(CpuArch::V4T) => return Ok(Some(unarm::ArmVersion::V4T)),
|
Some(CpuArch::V4T) => return Ok(Some(unarm::ArmVersion::V4T)),
|
||||||
@@ -358,11 +354,7 @@ impl Arch for ArchArm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn symbol_address(&self, address: u64, kind: SymbolKind) -> u64 {
|
fn symbol_address(&self, address: u64, kind: SymbolKind) -> u64 {
|
||||||
if kind == SymbolKind::Function {
|
if kind == SymbolKind::Function { address & !1 } else { address }
|
||||||
address & !1
|
|
||||||
} else {
|
|
||||||
address
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extra_symbol_flags(&self, symbol: &object::Symbol) -> SymbolFlagSet {
|
fn extra_symbol_flags(&self, symbol: &object::Symbol) -> SymbolFlagSet {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use alloc::{
|
|||||||
};
|
};
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{Result, bail};
|
||||||
use object::elf;
|
use object::elf;
|
||||||
use yaxpeax_arch::{Arch as YaxpeaxArch, Decoder, Reader, U8Reader};
|
use yaxpeax_arch::{Arch as YaxpeaxArch, Decoder, Reader, U8Reader};
|
||||||
use yaxpeax_arm::armv8::a64::{
|
use yaxpeax_arm::armv8::a64::{
|
||||||
@@ -15,7 +15,7 @@ use yaxpeax_arm::armv8::a64::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::Arch,
|
arch::Arch,
|
||||||
diff::{display::InstructionPart, DiffObjConfig},
|
diff::{DiffObjConfig, display::InstructionPart},
|
||||||
obj::{
|
obj::{
|
||||||
InstructionRef, RelocationFlags, ResolvedInstructionRef, ResolvedRelocation,
|
InstructionRef, RelocationFlags, ResolvedInstructionRef, ResolvedRelocation,
|
||||||
ScannedInstruction,
|
ScannedInstruction,
|
||||||
@@ -216,11 +216,7 @@ where Cb: FnMut(InstructionPart<'static>) {
|
|||||||
unreachable!("movn operand 1 is always ImmShift");
|
unreachable!("movn operand 1 is always ImmShift");
|
||||||
};
|
};
|
||||||
let imm = if let Operand::Register(size, _) = ins.operands[0] {
|
let imm = if let Operand::Register(size, _) = ins.operands[0] {
|
||||||
if size == SizeCode::W {
|
if size == SizeCode::W { imm as u32 as u64 } else { imm }
|
||||||
imm as u32 as u64
|
|
||||||
} else {
|
|
||||||
imm
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
unreachable!("movn operand 0 is always Register");
|
unreachable!("movn operand 0 is always Register");
|
||||||
};
|
};
|
||||||
@@ -237,11 +233,7 @@ where Cb: FnMut(InstructionPart<'static>) {
|
|||||||
unreachable!("movz operand is always ImmShift");
|
unreachable!("movz operand is always ImmShift");
|
||||||
};
|
};
|
||||||
let imm = if let Operand::Register(size, _) = ins.operands[0] {
|
let imm = if let Operand::Register(size, _) = ins.operands[0] {
|
||||||
if size == SizeCode::W {
|
if size == SizeCode::W { imm as u32 as u64 } else { imm }
|
||||||
imm as u32 as u64
|
|
||||||
} else {
|
|
||||||
imm
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
unreachable!("movz operand 0 is always Register");
|
unreachable!("movz operand 0 is always Register");
|
||||||
};
|
};
|
||||||
@@ -574,11 +566,7 @@ where Cb: FnMut(InstructionPart<'static>) {
|
|||||||
{
|
{
|
||||||
if immr < imms {
|
if immr < imms {
|
||||||
let size = if let Operand::Register(size, _) = ins.operands[0] {
|
let size = if let Operand::Register(size, _) = ins.operands[0] {
|
||||||
if size == SizeCode::W {
|
if size == SizeCode::W { 32 } else { 64 }
|
||||||
32
|
|
||||||
} else {
|
|
||||||
64
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
unreachable!("operand 0 is always a register");
|
unreachable!("operand 0 is always a register");
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
use alloc::{collections::BTreeMap, string::ToString, vec::Vec};
|
use alloc::{collections::BTreeMap, string::ToString, vec::Vec};
|
||||||
use core::ops::Range;
|
use core::ops::Range;
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{Result, bail};
|
||||||
use object::{elf, Endian as _, Object as _, ObjectSection as _, ObjectSymbol as _};
|
use object::{Endian as _, Object as _, ObjectSection as _, ObjectSymbol as _, elf};
|
||||||
use rabbitizer::{
|
use rabbitizer::{
|
||||||
abi::Abi,
|
|
||||||
operands::{ValuedOperand, IU16},
|
|
||||||
registers_meta::Register,
|
|
||||||
IsaExtension, IsaVersion, Vram,
|
IsaExtension, IsaVersion, Vram,
|
||||||
|
abi::Abi,
|
||||||
|
operands::{IU16, ValuedOperand},
|
||||||
|
registers_meta::Register,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::Arch,
|
arch::Arch,
|
||||||
diff::{display::InstructionPart, DiffObjConfig, MipsAbi, MipsInstrCategory},
|
diff::{DiffObjConfig, MipsAbi, MipsInstrCategory, display::InstructionPart},
|
||||||
obj::{
|
obj::{
|
||||||
InstructionArg, InstructionArgValue, InstructionRef, Relocation, RelocationFlags,
|
InstructionArg, InstructionArgValue, InstructionRef, Relocation, RelocationFlags,
|
||||||
ResolvedInstructionRef, ResolvedRelocation, ScannedInstruction,
|
ResolvedInstructionRef, ResolvedRelocation, ScannedInstruction,
|
||||||
@@ -144,9 +144,11 @@ impl ArchMips {
|
|||||||
|
|
||||||
fn instruction_display_flags(
|
fn instruction_display_flags(
|
||||||
&self,
|
&self,
|
||||||
_diff_config: &DiffObjConfig,
|
diff_config: &DiffObjConfig,
|
||||||
) -> rabbitizer::InstructionDisplayFlags {
|
) -> rabbitizer::InstructionDisplayFlags {
|
||||||
rabbitizer::InstructionDisplayFlags::default().with_unknown_instr_comment(false)
|
rabbitizer::InstructionDisplayFlags::default()
|
||||||
|
.with_unknown_instr_comment(false)
|
||||||
|
.with_use_dollar(diff_config.mips_register_prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_ins_ref(
|
fn parse_ins_ref(
|
||||||
@@ -207,7 +209,6 @@ impl Arch for ArchMips {
|
|||||||
function_range,
|
function_range,
|
||||||
resolved.section_index,
|
resolved.section_index,
|
||||||
&display_flags,
|
&display_flags,
|
||||||
diff_config,
|
|
||||||
cb,
|
cb,
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -301,7 +302,6 @@ fn push_args(
|
|||||||
function_range: Range<u64>,
|
function_range: Range<u64>,
|
||||||
section_index: usize,
|
section_index: usize,
|
||||||
display_flags: &rabbitizer::InstructionDisplayFlags,
|
display_flags: &rabbitizer::InstructionDisplayFlags,
|
||||||
diff_config: &DiffObjConfig,
|
|
||||||
mut arg_cb: impl FnMut(InstructionPart) -> Result<()>,
|
mut arg_cb: impl FnMut(InstructionPart) -> Result<()>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let operands = instruction.valued_operands_iter();
|
let operands = instruction.valued_operands_iter();
|
||||||
@@ -361,14 +361,11 @@ fn push_args(
|
|||||||
})))?;
|
})))?;
|
||||||
}
|
}
|
||||||
arg_cb(InstructionPart::basic("("))?;
|
arg_cb(InstructionPart::basic("("))?;
|
||||||
let mut value =
|
arg_cb(InstructionPart::opaque(base.either_name(
|
||||||
base.either_name(instruction.flags().abi(), display_flags.named_gpr());
|
instruction.flags().abi(),
|
||||||
if !diff_config.mips_register_prefix {
|
display_flags.named_gpr(),
|
||||||
if let Some(trimmed) = value.strip_prefix('$') {
|
!display_flags.use_dollar(),
|
||||||
value = trimmed;
|
)))?;
|
||||||
}
|
|
||||||
}
|
|
||||||
arg_cb(InstructionPart::opaque(value))?;
|
|
||||||
arg_cb(InstructionPart::basic(")"))?;
|
arg_cb(InstructionPart::basic(")"))?;
|
||||||
}
|
}
|
||||||
// ValuedOperand::r5900_immediate15(..) => match relocation {
|
// ValuedOperand::r5900_immediate15(..) => match relocation {
|
||||||
@@ -382,14 +379,9 @@ fn push_args(
|
|||||||
// }
|
// }
|
||||||
// },
|
// },
|
||||||
_ => {
|
_ => {
|
||||||
let value = op.display(instruction, display_flags, None::<&str>).to_string();
|
arg_cb(InstructionPart::opaque(
|
||||||
if !diff_config.mips_register_prefix {
|
op.display(instruction, display_flags, None::<&str>).to_string(),
|
||||||
if let Some(value) = value.strip_prefix('$') {
|
))?;
|
||||||
arg_cb(InstructionPart::opaque(value))?;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arg_cb(InstructionPart::opaque(value))?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
use alloc::{borrow::Cow, boxed::Box, format, string::String, vec::Vec};
|
use alloc::{borrow::Cow, boxed::Box, format, string::String, vec::Vec};
|
||||||
use core::{ffi::CStr, fmt, fmt::Debug};
|
use core::{ffi::CStr, fmt, fmt::Debug};
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{Result, bail};
|
||||||
use object::Endian as _;
|
use object::Endian as _;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
diff::{
|
diff::{
|
||||||
display::{ContextItem, HoverItem, InstructionPart},
|
|
||||||
DiffObjConfig,
|
DiffObjConfig,
|
||||||
|
display::{ContextItem, HoverItem, InstructionPart},
|
||||||
},
|
},
|
||||||
obj::{
|
obj::{
|
||||||
InstructionArg, Object, ParsedInstruction, RelocationFlags, ResolvedInstructionRef,
|
InstructionArg, Object, ParsedInstruction, Relocation, RelocationFlags,
|
||||||
ScannedInstruction, SymbolFlagSet, SymbolKind,
|
ResolvedInstructionRef, ScannedInstruction, Symbol, SymbolFlagSet, SymbolKind,
|
||||||
},
|
},
|
||||||
util::ReallySigned,
|
util::ReallySigned,
|
||||||
};
|
};
|
||||||
@@ -66,7 +66,9 @@ impl DataType {
|
|||||||
pub fn display_literals(&self, endian: object::Endianness, bytes: &[u8]) -> Vec<String> {
|
pub fn display_literals(&self, endian: object::Endianness, bytes: &[u8]) -> Vec<String> {
|
||||||
let mut strs = Vec::new();
|
let mut strs = Vec::new();
|
||||||
if self.required_len().is_some_and(|l| bytes.len() < l) {
|
if self.required_len().is_some_and(|l| bytes.len() < l) {
|
||||||
log::warn!("Failed to display a symbol value for a symbol whose size is too small for instruction referencing it.");
|
log::warn!(
|
||||||
|
"Failed to display a symbol value for a symbol whose size is too small for instruction referencing it."
|
||||||
|
);
|
||||||
return strs;
|
return strs;
|
||||||
}
|
}
|
||||||
let mut bytes = bytes;
|
let mut bytes = bytes;
|
||||||
@@ -212,6 +214,17 @@ pub trait Arch: Send + Sync + Debug {
|
|||||||
cb: &mut dyn FnMut(InstructionPart) -> Result<()>,
|
cb: &mut dyn FnMut(InstructionPart) -> Result<()>,
|
||||||
) -> Result<()>;
|
) -> Result<()>;
|
||||||
|
|
||||||
|
/// Generate a list of fake relocations from the given code that represent pooled data accesses.
|
||||||
|
fn generate_pooled_relocations(
|
||||||
|
&self,
|
||||||
|
_address: u64,
|
||||||
|
_code: &[u8],
|
||||||
|
_relocations: &[Relocation],
|
||||||
|
_symbols: &[Symbol],
|
||||||
|
) -> Vec<Relocation> {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
|
||||||
fn implcit_addend(
|
fn implcit_addend(
|
||||||
&self,
|
&self,
|
||||||
file: &object::File<'_>,
|
file: &object::File<'_>,
|
||||||
|
|||||||
@@ -1,24 +1,25 @@
|
|||||||
use alloc::{
|
use alloc::{
|
||||||
collections::BTreeMap,
|
collections::{BTreeMap, BTreeSet},
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
vec,
|
vec,
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{bail, ensure, Result};
|
use anyhow::{Result, bail, ensure};
|
||||||
use cwextab::{decode_extab, ExceptionTableData};
|
use cwextab::{ExceptionTableData, decode_extab};
|
||||||
use flagset::Flags;
|
use flagset::Flags;
|
||||||
use object::{elf, Object as _, ObjectSection as _, ObjectSymbol as _};
|
use object::{Object as _, ObjectSection as _, ObjectSymbol as _, elf};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{Arch, DataType},
|
arch::{Arch, DataType},
|
||||||
diff::{
|
diff::{
|
||||||
display::{ContextItem, HoverItem, HoverItemColor, InstructionPart, SymbolNavigationKind},
|
|
||||||
DiffObjConfig,
|
DiffObjConfig,
|
||||||
|
data::resolve_relocation,
|
||||||
|
display::{ContextItem, HoverItem, HoverItemColor, InstructionPart, SymbolNavigationKind},
|
||||||
},
|
},
|
||||||
obj::{
|
obj::{
|
||||||
InstructionRef, Object, Relocation, RelocationFlags, ResolvedInstructionRef,
|
InstructionRef, Object, Relocation, RelocationFlags, ResolvedInstructionRef,
|
||||||
ResolvedRelocation, ScannedInstruction, SymbolFlag, SymbolFlagSet,
|
ResolvedRelocation, ScannedInstruction, Symbol, SymbolFlag, SymbolFlagSet,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -157,6 +158,16 @@ impl Arch for ArchPpc {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_pooled_relocations(
|
||||||
|
&self,
|
||||||
|
address: u64,
|
||||||
|
code: &[u8],
|
||||||
|
relocations: &[Relocation],
|
||||||
|
symbols: &[Symbol],
|
||||||
|
) -> Vec<Relocation> {
|
||||||
|
generate_fake_pool_relocations_for_function(address, code, relocations, symbols)
|
||||||
|
}
|
||||||
|
|
||||||
fn implcit_addend(
|
fn implcit_addend(
|
||||||
&self,
|
&self,
|
||||||
_file: &object::File<'_>,
|
_file: &object::File<'_>,
|
||||||
@@ -501,21 +512,26 @@ fn guess_data_type_from_load_store_inst_op(inst_op: ppc750cl::Opcode) -> Option<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given an instruction, determine if it could accessing data at the address in a register.
|
struct PoolReference {
|
||||||
// If so, return the offset added to the register's address, the register containing that address,
|
addr_src_gpr: ppc750cl::GPR,
|
||||||
// and (optionally) which destination register the address is being copied into.
|
addr_offset: i16,
|
||||||
#[expect(unused)]
|
addr_dst_gpr: Option<ppc750cl::GPR>,
|
||||||
fn get_offset_and_addr_gpr_for_possible_pool_reference(
|
}
|
||||||
|
|
||||||
|
// Given an instruction, check if it could be accessing pooled data at the address in a register.
|
||||||
|
// If so, return information pertaining to where the instruction is getting that address from and
|
||||||
|
// what it's doing with the address (e.g. copying it into another register, adding an offset, etc).
|
||||||
|
fn get_pool_reference_for_inst(
|
||||||
opcode: ppc750cl::Opcode,
|
opcode: ppc750cl::Opcode,
|
||||||
simplified: &ppc750cl::ParsedIns,
|
simplified: &ppc750cl::ParsedIns,
|
||||||
) -> Option<(i16, ppc750cl::GPR, Option<ppc750cl::GPR>)> {
|
) -> Option<PoolReference> {
|
||||||
use ppc750cl::{Argument, Opcode};
|
use ppc750cl::{Argument, Opcode};
|
||||||
let args = &simplified.args;
|
let args = &simplified.args;
|
||||||
if guess_data_type_from_load_store_inst_op(opcode).is_some() {
|
if guess_data_type_from_load_store_inst_op(opcode).is_some() {
|
||||||
match (args[1], args[2]) {
|
match (args[1], args[2]) {
|
||||||
(Argument::Offset(offset), Argument::GPR(addr_src_gpr)) => {
|
(Argument::Offset(offset), Argument::GPR(addr_src_gpr)) => {
|
||||||
// e.g. lwz. Immediate offset.
|
// e.g. lwz. Immediate offset.
|
||||||
Some((offset.0, addr_src_gpr, None))
|
Some(PoolReference { addr_src_gpr, addr_offset: offset.0, addr_dst_gpr: None })
|
||||||
}
|
}
|
||||||
(Argument::GPR(addr_src_gpr), Argument::GPR(_offset_gpr)) => {
|
(Argument::GPR(addr_src_gpr), Argument::GPR(_offset_gpr)) => {
|
||||||
// e.g. lwzx. The offset is in a register and was likely calculated from an index.
|
// e.g. lwzx. The offset is in a register and was likely calculated from an index.
|
||||||
@@ -523,7 +539,7 @@ fn get_offset_and_addr_gpr_for_possible_pool_reference(
|
|||||||
// It may be possible to show all elements by figuring out the stride of the array
|
// It may be possible to show all elements by figuring out the stride of the array
|
||||||
// from the calculations performed on the index before it's put into offset_gpr, but
|
// from the calculations performed on the index before it's put into offset_gpr, but
|
||||||
// this would be much more complicated, so it's not currently done.
|
// this would be much more complicated, so it's not currently done.
|
||||||
Some((0, addr_src_gpr, None))
|
Some(PoolReference { addr_src_gpr, addr_offset: 0, addr_dst_gpr: None })
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
@@ -541,20 +557,32 @@ fn get_offset_and_addr_gpr_for_possible_pool_reference(
|
|||||||
Argument::GPR(addr_dst_gpr),
|
Argument::GPR(addr_dst_gpr),
|
||||||
Argument::GPR(addr_src_gpr),
|
Argument::GPR(addr_src_gpr),
|
||||||
Argument::Simm(simm),
|
Argument::Simm(simm),
|
||||||
) => Some((simm.0, addr_src_gpr, Some(addr_dst_gpr))),
|
) => Some(PoolReference {
|
||||||
|
addr_src_gpr,
|
||||||
|
addr_offset: simm.0,
|
||||||
|
addr_dst_gpr: Some(addr_dst_gpr),
|
||||||
|
}),
|
||||||
(
|
(
|
||||||
// `mr` or `mr.`
|
// `mr` or `mr.`
|
||||||
Opcode::Or,
|
Opcode::Or,
|
||||||
Argument::GPR(addr_dst_gpr),
|
Argument::GPR(addr_dst_gpr),
|
||||||
Argument::GPR(addr_src_gpr),
|
Argument::GPR(addr_src_gpr),
|
||||||
Argument::None,
|
Argument::None,
|
||||||
) => Some((0, addr_src_gpr, Some(addr_dst_gpr))),
|
) => Some(PoolReference {
|
||||||
|
addr_src_gpr,
|
||||||
|
addr_offset: 0,
|
||||||
|
addr_dst_gpr: Some(addr_dst_gpr),
|
||||||
|
}),
|
||||||
(
|
(
|
||||||
Opcode::Add,
|
Opcode::Add,
|
||||||
Argument::GPR(addr_dst_gpr),
|
Argument::GPR(addr_dst_gpr),
|
||||||
Argument::GPR(addr_src_gpr),
|
Argument::GPR(addr_src_gpr),
|
||||||
Argument::GPR(_offset_gpr),
|
Argument::GPR(_offset_gpr),
|
||||||
) => Some((0, addr_src_gpr, Some(addr_dst_gpr))),
|
) => Some(PoolReference {
|
||||||
|
addr_src_gpr,
|
||||||
|
addr_offset: 0,
|
||||||
|
addr_dst_gpr: Some(addr_dst_gpr),
|
||||||
|
}),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -562,7 +590,6 @@ fn get_offset_and_addr_gpr_for_possible_pool_reference(
|
|||||||
|
|
||||||
// Remove the relocation we're keeping track of in a particular register when an instruction reuses
|
// Remove the relocation we're keeping track of in a particular register when an instruction reuses
|
||||||
// that register to hold some other value, unrelated to pool relocation addresses.
|
// that register to hold some other value, unrelated to pool relocation addresses.
|
||||||
#[expect(unused)]
|
|
||||||
fn clear_overwritten_gprs(ins: ppc750cl::Ins, gpr_pool_relocs: &mut BTreeMap<u8, Relocation>) {
|
fn clear_overwritten_gprs(ins: ppc750cl::Ins, gpr_pool_relocs: &mut BTreeMap<u8, Relocation>) {
|
||||||
use ppc750cl::{Argument, Arguments, Opcode};
|
use ppc750cl::{Argument, Arguments, Opcode};
|
||||||
let mut def_args = Arguments::default();
|
let mut def_args = Arguments::default();
|
||||||
@@ -582,250 +609,238 @@ fn clear_overwritten_gprs(ins: ppc750cl::Ins, gpr_pool_relocs: &mut BTreeMap<u8,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
// We create a fake relocation for an instruction, vaguely simulating what the actual relocation
|
||||||
// // We create a fake relocation for an instruction, vaguely simulating what the actual relocation
|
// might have looked like if it wasn't pooled. This is so minimal changes are needed to display
|
||||||
// // might have looked like if it wasn't pooled. This is so minimal changes are needed to display
|
// pooled accesses vs non-pooled accesses. We set the relocation type to R_PPC_NONE to indicate that
|
||||||
// // pooled accesses vs non-pooled accesses. We set the relocation type to R_PPC_NONE to indicate that
|
// there isn't really a relocation here, as copying the pool relocation's type wouldn't make sense.
|
||||||
// // there isn't really a relocation here, as copying the pool relocation's type wouldn't make sense.
|
// Also, if this instruction is accessing the middle of a symbol instead of the start, we add an
|
||||||
// // Also, if this instruction is accessing the middle of a symbol instead of the start, we add an
|
// addend to indicate that.
|
||||||
// // addend to indicate that.
|
fn make_fake_pool_reloc(
|
||||||
// fn make_fake_pool_reloc(offset: i16, cur_addr: u32, pool_reloc: &Relocation) -> Option<Relocation> {
|
offset: i16,
|
||||||
// let offset_from_pool = pool_reloc.addend + offset as i64;
|
cur_addr: u32,
|
||||||
// let target_address = pool_reloc.sy.address.checked_add_signed(offset_from_pool)?;
|
pool_reloc: &Relocation,
|
||||||
// let target;
|
symbols: &[Symbol],
|
||||||
// let addend;
|
) -> Option<Relocation> {
|
||||||
// if pool_reloc.target.orig_section_index.is_some() {
|
let pool_reloc = resolve_relocation(symbols, pool_reloc);
|
||||||
// // If the target symbol is within this current object, then we also need to create a fake
|
let offset_from_pool = pool_reloc.relocation.addend + offset as i64;
|
||||||
// // target symbol to go inside our fake relocation. This is because we don't have access to
|
let target_address = pool_reloc.symbol.address.checked_add_signed(offset_from_pool)?;
|
||||||
// // list of all symbols in this section, so we can't find the real symbol within the pool
|
let target_symbol;
|
||||||
// // based on its address yet. Instead we make a placeholder that has the correct
|
let addend;
|
||||||
// // `orig_section_index` and `address` fields, and then later on when this information is
|
if let Some(section_index) = pool_reloc.symbol.section {
|
||||||
// // displayed to the user, we can find the real symbol by searching through the object's
|
// Find the exact data symbol within the pool being accessed here based on the address.
|
||||||
// // section's symbols for one that contains this address.
|
target_symbol = symbols.iter().position(|s| {
|
||||||
// target = ObjSymbol {
|
s.section == Some(section_index)
|
||||||
// name: "".to_string(),
|
&& s.size > 0
|
||||||
// demangled_name: None,
|
&& (s.address..s.address + s.size).contains(&target_address)
|
||||||
// address: target_address,
|
})?;
|
||||||
// section_address: 0,
|
addend = target_address.checked_sub(symbols[target_symbol].address)? as i64;
|
||||||
// size: 0,
|
} else {
|
||||||
// size_known: false,
|
// If the target symbol is in a different object (extern), we simply copy the pool
|
||||||
// kind: Default::default(),
|
// relocation's target. This is because it's not possible to locate the actual symbol if
|
||||||
// flags: Default::default(),
|
// it's extern. And doing that for external symbols would also be unnecessary, because when
|
||||||
// orig_section_index: pool_reloc.target.orig_section_index,
|
// the compiler generates an instruction that accesses an external "pool" plus some offset,
|
||||||
// virtual_address: None,
|
// that won't be a normal pool that contains other symbols within it that we want to
|
||||||
// original_index: None,
|
// display. It will be something like a vtable for a class with multiple inheritance (for
|
||||||
// bytes: vec![],
|
// example, dCcD_Cyl in The Wind Waker). So just showing that vtable symbol plus an addend
|
||||||
// };
|
// to represent the offset into it works fine in this case.
|
||||||
// // The addend is also fake because we don't know yet if the `target_address` here is the exact
|
target_symbol = pool_reloc.relocation.target_symbol;
|
||||||
// // start of the symbol or if it's in the middle of it.
|
addend = pool_reloc.relocation.addend + offset_from_pool;
|
||||||
// addend = 0;
|
}
|
||||||
// } else {
|
Some(Relocation {
|
||||||
// // But if the target symbol is in a different object (extern), then we simply copy the pool
|
flags: RelocationFlags::Elf(elf::R_PPC_NONE),
|
||||||
// // relocation's target. This is because it won't be possible to locate the actual symbol
|
address: cur_addr as u64,
|
||||||
// // later on based only off of an offset without knowing the object or section it's in. And
|
target_symbol,
|
||||||
// // doing that for external symbols would also be unnecessary, because when the compiler
|
addend,
|
||||||
// // generates an instruction that accesses an external "pool" plus some offset, that won't be
|
})
|
||||||
// // a normal pool that contains other symbols within it that we want to display. It will be
|
}
|
||||||
// // something like a vtable for a class with multiple inheritance (for example, dCcD_Cyl in
|
|
||||||
// // The Wind Waker). So just showing that vtable symbol plus an addend to represent the
|
// Searches through all instructions in a function, determining which registers have the addresses
|
||||||
// // offset into it works fine in this case, no fake symbol to hold an address is necessary.
|
// of pooled data relocations in them, finding which instructions load data from those addresses,
|
||||||
// target = pool_reloc.target.clone();
|
// and returns a Vec of "fake pool relocations" that simulate what a relocation for that instruction
|
||||||
// addend = pool_reloc.addend;
|
// would look like if data hadn't been pooled.
|
||||||
// };
|
// This method tries to follow the function's proper control flow. It keeps track of a queue of
|
||||||
// Some(ObjReloc {
|
// states it hasn't traversed yet, where each state holds an instruction address and a HashMap of
|
||||||
// flags: RelocationFlags::Elf { r_type: elf::R_PPC_NONE },
|
// which registers hold which pool relocations at that point.
|
||||||
// address: cur_addr as u64,
|
// When a conditional or unconditional branch is encountered, the destination of the branch is added
|
||||||
// target,
|
// to the queue. Conditional branches will traverse both the path where the branch is taken and the
|
||||||
// addend,
|
// one where it's not. Unconditional branches only follow the branch, ignoring any code immediately
|
||||||
// })
|
// after the branch instruction.
|
||||||
// }
|
// Limitations: This method does not currently read switch statement jump tables.
|
||||||
//
|
// Instead, we guess that any parts of a function we missed were switch cases, and traverse them as
|
||||||
// // Searches through all instructions in a function, determining which registers have the addresses
|
// if the last `bctr` before that address had branched there. This should be fairly accurate in
|
||||||
// // of pooled data relocations in them, finding which instructions load data from those addresses,
|
// practice - in testing the only instructions it seems to miss are double branches that the
|
||||||
// // and constructing a mapping of the address of that instruction to a "fake pool relocation" that
|
// compiler generates in error which can never be reached during normal execution anyway.
|
||||||
// // simulates what that instruction's relocation would look like if data hadn't been pooled.
|
// It should be possible to implement jump tables properly by reading them out of .data. But this
|
||||||
// // This method tries to follow the function's proper control flow. It keeps track of a queue of
|
// will require keeping track of what value is loaded into each register so we can retrieve the jump
|
||||||
// // states it hasn't traversed yet, where each state holds an instruction address and a HashMap of
|
// table symbol when we encounter a `bctr`.
|
||||||
// // which registers hold which pool relocations at that point.
|
fn generate_fake_pool_relocations_for_function(
|
||||||
// // When a conditional or unconditional branch is encountered, the destination of the branch is added
|
func_address: u64,
|
||||||
// // to the queue. Conditional branches will traverse both the path where the branch is taken and the
|
code: &[u8],
|
||||||
// // one where it's not. Unconditional branches only follow the branch, ignoring any code immediately
|
relocations: &[Relocation],
|
||||||
// // after the branch instruction.
|
symbols: &[Symbol],
|
||||||
// // Limitations: This method cannot read jump tables. This is because the jump tables are located in
|
) -> Vec<Relocation> {
|
||||||
// // the .data section, but ObjArch.process_code only has access to the .text section. In order to
|
use ppc750cl::{Argument, InsIter, Opcode};
|
||||||
// // work around this limitation and avoid completely missing most code inside switch statements that
|
let mut visited_ins_addrs = BTreeSet::new();
|
||||||
// // use jump tables, we instead guess that any parts of a function we missed were switch cases, and
|
let mut pool_reloc_for_addr = BTreeMap::new();
|
||||||
// // traverse them as if the last `bctr` before that address had branched there. This should be fairly
|
let mut ins_iters_with_gpr_state =
|
||||||
// // accurate in practice - in testing the only instructions it seems to miss are double branches that
|
vec![(InsIter::new(code, func_address as u32), BTreeMap::new())];
|
||||||
// // the compiler generates in error which can never be reached during normal execution anyway.
|
let mut gpr_state_at_bctr = BTreeMap::new();
|
||||||
// fn generate_fake_pool_reloc_for_addr_mapping(
|
while let Some((ins_iter, mut gpr_pool_relocs)) = ins_iters_with_gpr_state.pop() {
|
||||||
// func_address: u64,
|
for (cur_addr, ins) in ins_iter {
|
||||||
// code: &[u8],
|
if visited_ins_addrs.contains(&cur_addr) {
|
||||||
// relocations: &[ObjReloc],
|
// Avoid getting stuck in an infinite loop when following looping branches.
|
||||||
// ) -> BTreeMap<u32, ObjReloc> {
|
break;
|
||||||
// let mut visited_ins_addrs = BTreeSet::new();
|
}
|
||||||
// let mut pool_reloc_for_addr = BTreeMap::new();
|
visited_ins_addrs.insert(cur_addr);
|
||||||
// let mut ins_iters_with_gpr_state =
|
|
||||||
// vec![(InsIter::new(code, func_address as u32), BTreeMap::new())];
|
let simplified = ins.simplified();
|
||||||
// let mut gpr_state_at_bctr = BTreeMap::new();
|
|
||||||
// while let Some((ins_iter, mut gpr_pool_relocs)) = ins_iters_with_gpr_state.pop() {
|
// First handle traversing the function's control flow.
|
||||||
// for (cur_addr, ins) in ins_iter {
|
let mut branch_dest = None;
|
||||||
// if visited_ins_addrs.contains(&cur_addr) {
|
for arg in simplified.args_iter() {
|
||||||
// // Avoid getting stuck in an infinite loop when following looping branches.
|
if let Argument::BranchDest(dest) = arg {
|
||||||
// break;
|
let dest = cur_addr.wrapping_add_signed(dest.0);
|
||||||
// }
|
branch_dest = Some(dest);
|
||||||
// visited_ins_addrs.insert(cur_addr);
|
break;
|
||||||
//
|
}
|
||||||
// let simplified = ins.simplified();
|
}
|
||||||
//
|
if let Some(branch_dest) = branch_dest {
|
||||||
// // First handle traversing the function's control flow.
|
if branch_dest >= func_address as u32
|
||||||
// let mut branch_dest = None;
|
&& (branch_dest - func_address as u32) < code.len() as u32
|
||||||
// for arg in simplified.args_iter() {
|
{
|
||||||
// if let Argument::BranchDest(dest) = arg {
|
let dest_offset_into_func = branch_dest - func_address as u32;
|
||||||
// let dest = cur_addr.wrapping_add_signed(dest.0);
|
let dest_code_slice = &code[dest_offset_into_func as usize..];
|
||||||
// branch_dest = Some(dest);
|
match ins.op {
|
||||||
// break;
|
Opcode::Bc => {
|
||||||
// }
|
// Conditional branch.
|
||||||
// }
|
// Add the branch destination to the queue to do later.
|
||||||
// if let Some(branch_dest) = branch_dest {
|
ins_iters_with_gpr_state.push((
|
||||||
// if branch_dest >= func_address as u32
|
InsIter::new(dest_code_slice, branch_dest),
|
||||||
// && (branch_dest - func_address as u32) < code.len() as u32
|
gpr_pool_relocs.clone(),
|
||||||
// {
|
));
|
||||||
// let dest_offset_into_func = branch_dest - func_address as u32;
|
// Then continue on with the current iterator.
|
||||||
// let dest_code_slice = &code[dest_offset_into_func as usize..];
|
}
|
||||||
// match ins.op {
|
Opcode::B => {
|
||||||
// Opcode::Bc => {
|
if simplified.mnemonic != "bl" {
|
||||||
// // Conditional branch.
|
// Unconditional branch.
|
||||||
// // Add the branch destination to the queue to do later.
|
// Add the branch destination to the queue.
|
||||||
// ins_iters_with_gpr_state.push((
|
ins_iters_with_gpr_state.push((
|
||||||
// InsIter::new(dest_code_slice, branch_dest),
|
InsIter::new(dest_code_slice, branch_dest),
|
||||||
// gpr_pool_relocs.clone(),
|
gpr_pool_relocs.clone(),
|
||||||
// ));
|
));
|
||||||
// // Then continue on with the current iterator.
|
// Break out of the current iterator so we can do the newly added one.
|
||||||
// }
|
break;
|
||||||
// Opcode::B => {
|
}
|
||||||
// if simplified.mnemonic != "bl" {
|
}
|
||||||
// // Unconditional branch.
|
_ => unreachable!(),
|
||||||
// // Add the branch destination to the queue.
|
}
|
||||||
// ins_iters_with_gpr_state.push((
|
}
|
||||||
// InsIter::new(dest_code_slice, branch_dest),
|
}
|
||||||
// gpr_pool_relocs.clone(),
|
if let Opcode::Bcctr = ins.op {
|
||||||
// ));
|
if simplified.mnemonic == "bctr" {
|
||||||
// // Break out of the current iterator so we can do the newly added one.
|
// Unconditional branch to count register.
|
||||||
// break;
|
// Likely a jump table.
|
||||||
// }
|
gpr_state_at_bctr.insert(cur_addr, gpr_pool_relocs.clone());
|
||||||
// }
|
}
|
||||||
// _ => unreachable!(),
|
}
|
||||||
// }
|
|
||||||
// }
|
// Then handle keeping track of which GPR contains which pool relocation.
|
||||||
// }
|
let reloc = relocations.iter().find(|r| (r.address as u32 & !3) == cur_addr);
|
||||||
// if let Opcode::Bcctr = ins.op {
|
if let Some(reloc) = reloc {
|
||||||
// if simplified.mnemonic == "bctr" {
|
// This instruction has a real relocation, so it may be a pool load we want to keep
|
||||||
// // Unconditional branch to count register.
|
// track of.
|
||||||
// // Likely a jump table.
|
let args = &simplified.args;
|
||||||
// gpr_state_at_bctr.insert(cur_addr, gpr_pool_relocs.clone());
|
match (ins.op, args[0], args[1], args[2]) {
|
||||||
// }
|
(
|
||||||
// }
|
// `lis` + `addi`
|
||||||
//
|
Opcode::Addi,
|
||||||
// // Then handle keeping track of which GPR contains which pool relocation.
|
Argument::GPR(addr_dst_gpr),
|
||||||
// let reloc = relocations.iter().find(|r| (r.address as u32 & !3) == cur_addr);
|
Argument::GPR(_addr_src_gpr),
|
||||||
// if let Some(reloc) = reloc {
|
Argument::Simm(_simm),
|
||||||
// // This instruction has a real relocation, so it may be a pool load we want to keep
|
) => {
|
||||||
// // track of.
|
gpr_pool_relocs.insert(addr_dst_gpr.0, reloc.clone());
|
||||||
// let args = &simplified.args;
|
}
|
||||||
// match (ins.op, args[0], args[1], args[2]) {
|
(
|
||||||
// (
|
// `lis` + `ori`
|
||||||
// // `lis` + `addi`
|
Opcode::Ori,
|
||||||
// Opcode::Addi,
|
Argument::GPR(addr_dst_gpr),
|
||||||
// Argument::GPR(addr_dst_gpr),
|
Argument::GPR(_addr_src_gpr),
|
||||||
// Argument::GPR(_addr_src_gpr),
|
Argument::Uimm(_uimm),
|
||||||
// Argument::Simm(_simm),
|
) => {
|
||||||
// ) => {
|
gpr_pool_relocs.insert(addr_dst_gpr.0, reloc.clone());
|
||||||
// gpr_pool_relocs.insert(addr_dst_gpr.0, reloc.clone());
|
}
|
||||||
// }
|
(Opcode::B, _, _, _) => {
|
||||||
// (
|
if simplified.mnemonic == "bl" {
|
||||||
// // `lis` + `ori`
|
// When encountering a function call, clear any active pool relocations from
|
||||||
// Opcode::Ori,
|
// the volatile registers (r0, r3-r12), but not the nonvolatile registers.
|
||||||
// Argument::GPR(addr_dst_gpr),
|
gpr_pool_relocs.remove(&0);
|
||||||
// Argument::GPR(_addr_src_gpr),
|
for gpr in 3..12 {
|
||||||
// Argument::Uimm(_uimm),
|
gpr_pool_relocs.remove(&gpr);
|
||||||
// ) => {
|
}
|
||||||
// gpr_pool_relocs.insert(addr_dst_gpr.0, reloc.clone());
|
}
|
||||||
// }
|
}
|
||||||
// (Opcode::B, _, _, _) => {
|
_ => {
|
||||||
// if simplified.mnemonic == "bl" {
|
clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
|
||||||
// // When encountering a function call, clear any active pool relocations from
|
}
|
||||||
// // the volatile registers (r0, r3-r12), but not the nonvolatile registers.
|
}
|
||||||
// gpr_pool_relocs.remove(&0);
|
} else if let Some(pool_ref) = get_pool_reference_for_inst(ins.op, &simplified) {
|
||||||
// for gpr in 3..12 {
|
// This instruction doesn't have a real relocation, so it may be a reference to one of
|
||||||
// gpr_pool_relocs.remove(&gpr);
|
// the already-loaded pools.
|
||||||
// }
|
if let Some(pool_reloc) = gpr_pool_relocs.get(&pool_ref.addr_src_gpr.0) {
|
||||||
// }
|
if let Some(fake_pool_reloc) =
|
||||||
// }
|
make_fake_pool_reloc(pool_ref.addr_offset, cur_addr, pool_reloc, symbols)
|
||||||
// _ => {
|
{
|
||||||
// clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
|
pool_reloc_for_addr.insert(cur_addr, fake_pool_reloc);
|
||||||
// }
|
}
|
||||||
// }
|
if let Some(addr_dst_gpr) = pool_ref.addr_dst_gpr {
|
||||||
// } else if let Some((offset, addr_src_gpr, addr_dst_gpr)) =
|
// If the address of the pool relocation got copied into another register, we
|
||||||
// get_offset_and_addr_gpr_for_possible_pool_reference(ins.op, &simplified)
|
// need to keep track of it in that register too as future instructions may
|
||||||
// {
|
// reference the symbol indirectly via this new register, instead of the
|
||||||
// // This instruction doesn't have a real relocation, so it may be a reference to one of
|
// register the symbol's address was originally loaded into.
|
||||||
// // the already-loaded pools.
|
// For example, the start of the function might `lis` + `addi` the start of the
|
||||||
// if let Some(pool_reloc) = gpr_pool_relocs.get(&addr_src_gpr.0) {
|
// ...data pool into r25, and then later the start of a loop will `addi` r25
|
||||||
// if let Some(fake_pool_reloc) =
|
// with the offset within the .data section of an array variable into r21.
|
||||||
// make_fake_pool_reloc(offset, cur_addr, pool_reloc)
|
// Then the body of the loop will `lwzx` one of the array elements from r21.
|
||||||
// {
|
let mut new_reloc = pool_reloc.clone();
|
||||||
// pool_reloc_for_addr.insert(cur_addr, fake_pool_reloc);
|
new_reloc.addend += pool_ref.addr_offset as i64;
|
||||||
// }
|
gpr_pool_relocs.insert(addr_dst_gpr.0, new_reloc);
|
||||||
// if let Some(addr_dst_gpr) = addr_dst_gpr {
|
} else {
|
||||||
// // If the address of the pool relocation got copied into another register, we
|
clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
|
||||||
// // need to keep track of it in that register too as future instructions may
|
}
|
||||||
// // reference the symbol indirectly via this new register, instead of the
|
} else {
|
||||||
// // register the symbol's address was originally loaded into.
|
clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
|
||||||
// // For example, the start of the function might `lis` + `addi` the start of the
|
}
|
||||||
// // ...data pool into r25, and then later the start of a loop will `addi` r25
|
} else {
|
||||||
// // with the offset within the .data section of an array variable into r21.
|
clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
|
||||||
// // Then the body of the loop will `lwzx` one of the array elements from r21.
|
}
|
||||||
// let mut new_reloc = pool_reloc.clone();
|
}
|
||||||
// new_reloc.addend += offset as i64;
|
|
||||||
// gpr_pool_relocs.insert(addr_dst_gpr.0, new_reloc);
|
// Finally, if we're about to finish the outer loop and don't have any more control flow to
|
||||||
// } else {
|
// follow, we check if there are any instruction addresses in this function that we missed.
|
||||||
// clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
|
// If so, and if there were any `bctr` instructions before those points in this function,
|
||||||
// }
|
// then we try to traverse those missing spots as switch cases.
|
||||||
// } else {
|
if ins_iters_with_gpr_state.is_empty() {
|
||||||
// clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
|
let unseen_addrs = (func_address as u32..func_address as u32 + code.len() as u32)
|
||||||
// }
|
.step_by(4)
|
||||||
// } else {
|
.filter(|addr| !visited_ins_addrs.contains(addr));
|
||||||
// clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
|
for unseen_addr in unseen_addrs {
|
||||||
// }
|
let prev_bctr_gpr_state = gpr_state_at_bctr
|
||||||
// }
|
.iter()
|
||||||
//
|
.filter(|&(&addr, _)| addr < unseen_addr)
|
||||||
// // Finally, if we're about to finish the outer loop and don't have any more control flow to
|
.min_by_key(|&(&addr, _)| addr)
|
||||||
// // follow, we check if there are any instruction addresses in this function that we missed.
|
.map(|(_, gpr_state)| gpr_state);
|
||||||
// // If so, and if there were any `bctr` instructions before those points in this function,
|
if let Some(gpr_pool_relocs) = prev_bctr_gpr_state {
|
||||||
// // then we try to traverse those missing spots as switch cases.
|
let dest_offset_into_func = unseen_addr - func_address as u32;
|
||||||
// if ins_iters_with_gpr_state.is_empty() {
|
let dest_code_slice = &code[dest_offset_into_func as usize..];
|
||||||
// let unseen_addrs = (func_address as u32..func_address as u32 + code.len() as u32)
|
ins_iters_with_gpr_state.push((
|
||||||
// .step_by(4)
|
InsIter::new(dest_code_slice, unseen_addr),
|
||||||
// .filter(|addr| !visited_ins_addrs.contains(addr));
|
gpr_pool_relocs.clone(),
|
||||||
// for unseen_addr in unseen_addrs {
|
));
|
||||||
// let prev_bctr_gpr_state = gpr_state_at_bctr
|
break;
|
||||||
// .iter()
|
}
|
||||||
// .filter(|(&addr, _)| addr < unseen_addr)
|
}
|
||||||
// .min_by_key(|(&addr, _)| addr)
|
}
|
||||||
// .map(|(_, gpr_state)| gpr_state);
|
}
|
||||||
// if let Some(gpr_pool_relocs) = prev_bctr_gpr_state {
|
|
||||||
// let dest_offset_into_func = unseen_addr - func_address as u32;
|
pool_reloc_for_addr.values().cloned().collect()
|
||||||
// let dest_code_slice = &code[dest_offset_into_func as usize..];
|
}
|
||||||
// ins_iters_with_gpr_state.push((
|
|
||||||
// InsIter::new(dest_code_slice, unseen_addr),
|
|
||||||
// gpr_pool_relocs.clone(),
|
|
||||||
// ));
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// pool_reloc_for_addr
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
use alloc::{boxed::Box, string::String, vec::Vec};
|
use alloc::{boxed::Box, string::String, vec::Vec};
|
||||||
|
|
||||||
use anyhow::{anyhow, bail, Result};
|
use anyhow::{Result, anyhow, bail};
|
||||||
use iced_x86::{
|
use iced_x86::{
|
||||||
Decoder, DecoderOptions, DecoratorKind, FormatterOutput, FormatterTextKind, GasFormatter,
|
Decoder, DecoderOptions, DecoratorKind, FormatterOutput, FormatterTextKind, GasFormatter,
|
||||||
Instruction, IntelFormatter, MasmFormatter, NasmFormatter, NumberKind, OpKind, Register,
|
Instruction, IntelFormatter, MasmFormatter, NasmFormatter, NumberKind, OpKind, Register,
|
||||||
};
|
};
|
||||||
use object::{pe, Endian as _, Object as _, ObjectSection as _};
|
use object::{Endian as _, Object as _, ObjectSection as _, pe};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::Arch,
|
arch::Arch,
|
||||||
diff::{display::InstructionPart, DiffObjConfig, X86Formatter},
|
diff::{DiffObjConfig, X86Formatter, display::InstructionPart},
|
||||||
obj::{InstructionRef, RelocationFlags, ResolvedInstructionRef, ScannedInstruction},
|
obj::{InstructionRef, RelocationFlags, ResolvedInstructionRef, ScannedInstruction},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ impl Arch for ArchX86 {
|
|||||||
let mut reloc_replace = None;
|
let mut reloc_replace = None;
|
||||||
if let Some(reloc) = resolved.relocation {
|
if let Some(reloc) = resolved.relocation {
|
||||||
const PLACEHOLDER: u64 = 0x7BDE3E7D; // chosen by fair dice roll.
|
const PLACEHOLDER: u64 = 0x7BDE3E7D; // chosen by fair dice roll.
|
||||||
// guaranteed to be random.
|
// guaranteed to be random.
|
||||||
let reloc_offset = reloc.relocation.address - resolved.ins_ref.address;
|
let reloc_offset = reloc.relocation.address - resolved.ins_ref.address;
|
||||||
let reloc_size = reloc_size(reloc.relocation.flags).unwrap_or(usize::MAX);
|
let reloc_size = reloc_size(reloc.relocation.flags).unwrap_or(usize::MAX);
|
||||||
let offsets = decoder.get_constant_offsets(&instruction);
|
let offsets = decoder.get_constant_offsets(&instruction);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use alloc::{
|
|||||||
};
|
};
|
||||||
use core::ops::AddAssign;
|
use core::ops::AddAssign;
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{Result, bail};
|
||||||
use prost::Message;
|
use prost::Message;
|
||||||
|
|
||||||
// Protobuf report types
|
// Protobuf report types
|
||||||
@@ -441,11 +441,7 @@ impl From<LegacyReportItem> for ReportItem {
|
|||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
fn serialize_hex<S>(x: &Option<u64>, s: S) -> Result<S::Ok, S::Error>
|
fn serialize_hex<S>(x: &Option<u64>, s: S) -> Result<S::Ok, S::Error>
|
||||||
where S: serde::Serializer {
|
where S: serde::Serializer {
|
||||||
if let Some(x) = x {
|
if let Some(x) = x { s.serialize_str(&format!("{:#x}", x)) } else { s.serialize_none() }
|
||||||
s.serialize_str(&format!("{:#x}", x))
|
|
||||||
} else {
|
|
||||||
s.serialize_none()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ use std::{
|
|||||||
fs,
|
fs,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicBool, Ordering},
|
|
||||||
Arc,
|
Arc,
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
},
|
},
|
||||||
task::Waker,
|
task::Waker,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
@@ -11,7 +11,7 @@ use std::{
|
|||||||
|
|
||||||
use globset::GlobSet;
|
use globset::GlobSet;
|
||||||
use notify::RecursiveMode;
|
use notify::RecursiveMode;
|
||||||
use notify_debouncer_full::{new_debouncer_opt, DebounceEventResult};
|
use notify_debouncer_full::{DebounceEventResult, new_debouncer_opt};
|
||||||
|
|
||||||
pub type Watcher = notify_debouncer_full::Debouncer<
|
pub type Watcher = notify_debouncer_full::Debouncer<
|
||||||
notify::RecommendedWatcher,
|
notify::RecommendedWatcher,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use alloc::{
|
|||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{Context, Result, anyhow};
|
||||||
use globset::{Glob, GlobSet, GlobSetBuilder};
|
use globset::{Glob, GlobSet, GlobSetBuilder};
|
||||||
use path::unix_path_serde_option;
|
use path::unix_path_serde_option;
|
||||||
use typed_path::Utf8UnixPathBuf;
|
use typed_path::Utf8UnixPathBuf;
|
||||||
|
|||||||
@@ -31,11 +31,7 @@ pub mod unix_path_serde_option {
|
|||||||
|
|
||||||
pub fn serialize<S>(path: &Option<Utf8UnixPathBuf>, s: S) -> Result<S::Ok, S::Error>
|
pub fn serialize<S>(path: &Option<Utf8UnixPathBuf>, s: S) -> Result<S::Ok, S::Error>
|
||||||
where S: Serializer {
|
where S: Serializer {
|
||||||
if let Some(path) = path {
|
if let Some(path) = path { s.serialize_some(path.as_str()) } else { s.serialize_none() }
|
||||||
s.serialize_some(path.as_str())
|
|
||||||
} else {
|
|
||||||
s.serialize_none()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Utf8UnixPathBuf>, D::Error>
|
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Utf8UnixPathBuf>, D::Error>
|
||||||
@@ -51,11 +47,7 @@ pub mod platform_path_serde_option {
|
|||||||
|
|
||||||
pub fn serialize<S>(path: &Option<Utf8PlatformPathBuf>, s: S) -> Result<S::Ok, S::Error>
|
pub fn serialize<S>(path: &Option<Utf8PlatformPathBuf>, s: S) -> Result<S::Ok, S::Error>
|
||||||
where S: Serializer {
|
where S: Serializer {
|
||||||
if let Some(path) = path {
|
if let Some(path) = path { s.serialize_some(path.as_str()) } else { s.serialize_none() }
|
||||||
s.serialize_some(path.as_str())
|
|
||||||
} else {
|
|
||||||
s.serialize_none()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Utf8PlatformPathBuf>, D::Error>
|
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Utf8PlatformPathBuf>, D::Error>
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
use alloc::{
|
use alloc::{
|
||||||
collections::{btree_map, BTreeMap},
|
collections::{BTreeMap, btree_map},
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
vec,
|
vec,
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{anyhow, ensure, Context, Result};
|
use anyhow::{Context, Result, anyhow, ensure};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
display::display_ins_data_literals, DiffObjConfig, FunctionRelocDiffs, InstructionArgDiffIndex,
|
DiffObjConfig, FunctionRelocDiffs, InstructionArgDiffIndex, InstructionBranchFrom,
|
||||||
InstructionBranchFrom, InstructionBranchTo, InstructionDiffKind, InstructionDiffRow,
|
InstructionBranchTo, InstructionDiffKind, InstructionDiffRow, SymbolDiff,
|
||||||
SymbolDiff,
|
display::display_ins_data_literals,
|
||||||
};
|
};
|
||||||
use crate::obj::{
|
use crate::obj::{
|
||||||
InstructionArg, InstructionArgValue, InstructionRef, Object, ResolvedInstructionRef,
|
InstructionArg, InstructionArgValue, InstructionRef, Object, ResolvedInstructionRef,
|
||||||
@@ -502,17 +502,3 @@ fn diff_instruction(
|
|||||||
|
|
||||||
Ok(InstructionDiffResult::new(InstructionDiffKind::None))
|
Ok(InstructionDiffResult::new(InstructionDiffKind::None))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
|
||||||
// fn find_symbol_matching_fake_symbol_in_sections(
|
|
||||||
// fake_symbol: &ObjSymbol,
|
|
||||||
// sections: &[ObjSection],
|
|
||||||
// ) -> Option<ObjSymbol> {
|
|
||||||
// let orig_section_index = fake_symbol.orig_section_index?;
|
|
||||||
// let section = sections.iter().find(|s| s.orig_index == orig_section_index)?;
|
|
||||||
// let real_symbol = section
|
|
||||||
// .symbols
|
|
||||||
// .iter()
|
|
||||||
// .find(|s| s.size > 0 && (s.address..s.address + s.size).contains(&fake_symbol.address))?;
|
|
||||||
// Some(real_symbol.clone())
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
use alloc::{vec, vec::Vec};
|
use alloc::{vec, vec::Vec};
|
||||||
use core::{cmp::Ordering, ops::Range};
|
use core::{cmp::Ordering, ops::Range};
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{Result, anyhow};
|
||||||
use similar::{capture_diff_slices, get_diff_ratio, Algorithm};
|
use similar::{Algorithm, capture_diff_slices, get_diff_ratio};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
code::{address_eq, section_name_eq},
|
|
||||||
DataDiff, DataDiffKind, DataRelocationDiff, ObjectDiff, SectionDiff, SymbolDiff,
|
DataDiff, DataDiffKind, DataRelocationDiff, ObjectDiff, SectionDiff, SymbolDiff,
|
||||||
|
code::{address_eq, section_name_eq},
|
||||||
};
|
};
|
||||||
use crate::obj::{Object, Relocation, ResolvedRelocation, SymbolFlag, SymbolKind};
|
use crate::obj::{Object, Relocation, ResolvedRelocation, Symbol, SymbolFlag, SymbolKind};
|
||||||
|
|
||||||
pub fn diff_bss_symbol(
|
pub fn diff_bss_symbol(
|
||||||
left_obj: &Object,
|
left_obj: &Object,
|
||||||
@@ -64,10 +64,10 @@ fn reloc_eq(
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn resolve_relocation<'obj>(
|
pub fn resolve_relocation<'obj>(
|
||||||
obj: &'obj Object,
|
symbols: &'obj [Symbol],
|
||||||
reloc: &'obj Relocation,
|
reloc: &'obj Relocation,
|
||||||
) -> ResolvedRelocation<'obj> {
|
) -> ResolvedRelocation<'obj> {
|
||||||
let symbol = &obj.symbols[reloc.target_symbol];
|
let symbol = &symbols[reloc.target_symbol];
|
||||||
ResolvedRelocation { relocation: reloc, symbol }
|
ResolvedRelocation { relocation: reloc, symbol }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ fn diff_data_relocs_for_range<'left, 'right>(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let left_offset = left_reloc.address as usize - left_range.start;
|
let left_offset = left_reloc.address as usize - left_range.start;
|
||||||
let left_reloc = resolve_relocation(left_obj, left_reloc);
|
let left_reloc = resolve_relocation(&left_obj.symbols, left_reloc);
|
||||||
let Some(right_reloc) = right_section.relocations.iter().find(|r| {
|
let Some(right_reloc) = right_section.relocations.iter().find(|r| {
|
||||||
if !right_range.contains(&(r.address as usize)) {
|
if !right_range.contains(&(r.address as usize)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -99,7 +99,7 @@ fn diff_data_relocs_for_range<'left, 'right>(
|
|||||||
diffs.push((DataDiffKind::Delete, Some(left_reloc), None));
|
diffs.push((DataDiffKind::Delete, Some(left_reloc), None));
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let right_reloc = resolve_relocation(right_obj, right_reloc);
|
let right_reloc = resolve_relocation(&right_obj.symbols, right_reloc);
|
||||||
if reloc_eq(left_obj, right_obj, left_reloc, right_reloc) {
|
if reloc_eq(left_obj, right_obj, left_reloc, right_reloc) {
|
||||||
diffs.push((DataDiffKind::None, Some(left_reloc), Some(right_reloc)));
|
diffs.push((DataDiffKind::None, Some(left_reloc), Some(right_reloc)));
|
||||||
} else {
|
} else {
|
||||||
@@ -111,7 +111,7 @@ fn diff_data_relocs_for_range<'left, 'right>(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let right_offset = right_reloc.address as usize - right_range.start;
|
let right_offset = right_reloc.address as usize - right_range.start;
|
||||||
let right_reloc = resolve_relocation(right_obj, right_reloc);
|
let right_reloc = resolve_relocation(&right_obj.symbols, right_reloc);
|
||||||
let Some(_) = left_section.relocations.iter().find(|r| {
|
let Some(_) = left_section.relocations.iter().find(|r| {
|
||||||
if !left_range.contains(&(r.address as usize)) {
|
if !left_range.contains(&(r.address as usize)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -431,11 +431,7 @@ pub fn diff_generic_section(
|
|||||||
.fold((0.0, 0.0), |(matched, total), (s, d)| {
|
.fold((0.0, 0.0), |(matched, total), (s, d)| {
|
||||||
(matched + d.match_percent.unwrap_or(0.0) * s.size as f32, total + s.size as f32)
|
(matched + d.match_percent.unwrap_or(0.0) * s.size as f32, total + s.size as f32)
|
||||||
});
|
});
|
||||||
if total == 0.0 {
|
if total == 0.0 { 100.0 } else { matched / total }
|
||||||
100.0
|
|
||||||
} else {
|
|
||||||
matched / total
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
Ok((
|
Ok((
|
||||||
SectionDiff { match_percent: Some(match_percent), data_diff: vec![], reloc_diff: vec![] },
|
SectionDiff { match_percent: Some(match_percent), data_diff: vec![], reloc_diff: vec![] },
|
||||||
|
|||||||
@@ -26,13 +26,7 @@ pub mod display;
|
|||||||
include!(concat!(env!("OUT_DIR"), "/config.gen.rs"));
|
include!(concat!(env!("OUT_DIR"), "/config.gen.rs"));
|
||||||
|
|
||||||
impl DiffObjConfig {
|
impl DiffObjConfig {
|
||||||
pub fn separator(&self) -> &'static str {
|
pub fn separator(&self) -> &'static str { if self.space_between_args { ", " } else { "," } }
|
||||||
if self.space_between_args {
|
|
||||||
", "
|
|
||||||
} else {
|
|
||||||
","
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use self_update::{
|
|||||||
update::{Release, ReleaseUpdate},
|
update::{Release, ReleaseUpdate},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::jobs::{start_job, update_status, Job, JobContext, JobResult, JobState};
|
use crate::jobs::{Job, JobContext, JobResult, JobState, start_job, update_status};
|
||||||
|
|
||||||
pub struct CheckUpdateConfig {
|
pub struct CheckUpdateConfig {
|
||||||
pub build_updater: fn() -> Result<Box<dyn ReleaseUpdate>>,
|
pub build_updater: fn() -> Result<Box<dyn ReleaseUpdate>>,
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
use std::{fs, sync::mpsc::Receiver, task::Waker};
|
use std::{fs, sync::mpsc::Receiver, task::Waker};
|
||||||
|
|
||||||
use anyhow::{anyhow, bail, Context, Result};
|
use anyhow::{Context, Result, anyhow, bail};
|
||||||
use typed_path::{Utf8PlatformPathBuf, Utf8UnixPathBuf};
|
use typed_path::{Utf8PlatformPathBuf, Utf8UnixPathBuf};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
build::{run_make, BuildConfig, BuildStatus},
|
build::{BuildConfig, BuildStatus, run_make},
|
||||||
jobs::{start_job, update_status, Job, JobContext, JobResult, JobState},
|
jobs::{Job, JobContext, JobResult, JobState, start_job, update_status},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use std::{
|
use std::{
|
||||||
sync::{
|
sync::{
|
||||||
|
Arc, RwLock,
|
||||||
atomic::{AtomicUsize, Ordering},
|
atomic::{AtomicUsize, Ordering},
|
||||||
mpsc::{Receiver, Sender, TryRecvError},
|
mpsc::{Receiver, Sender, TryRecvError},
|
||||||
Arc, RwLock,
|
|
||||||
},
|
},
|
||||||
task::Waker,
|
task::Waker,
|
||||||
thread::JoinHandle,
|
thread::JoinHandle,
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
use std::{sync::mpsc::Receiver, task::Waker};
|
use std::{sync::mpsc::Receiver, task::Waker};
|
||||||
|
|
||||||
use anyhow::{bail, Error, Result};
|
use anyhow::{Error, Result, bail};
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use typed_path::Utf8PlatformPathBuf;
|
use typed_path::Utf8PlatformPathBuf;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
build::{run_make, BuildConfig, BuildStatus},
|
build::{BuildConfig, BuildStatus, run_make},
|
||||||
diff::{diff_objs, DiffObjConfig, MappingConfig, ObjectDiff},
|
diff::{DiffObjConfig, MappingConfig, ObjectDiff, diff_objs},
|
||||||
jobs::{start_job, update_status, Job, JobContext, JobResult, JobState},
|
jobs::{Job, JobContext, JobResult, JobState, start_job, update_status},
|
||||||
obj::{read, Object},
|
obj::{Object, read},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct ObjDiffConfig {
|
pub struct ObjDiffConfig {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use anyhow::{Context, Result};
|
|||||||
pub use self_update; // Re-export self_update crate
|
pub use self_update; // Re-export self_update crate
|
||||||
use self_update::update::ReleaseUpdate;
|
use self_update::update::ReleaseUpdate;
|
||||||
|
|
||||||
use crate::jobs::{start_job, update_status, Job, JobContext, JobResult, JobState};
|
use crate::jobs::{Job, JobContext, JobResult, JobState, start_job, update_status};
|
||||||
|
|
||||||
pub struct UpdateConfig {
|
pub struct UpdateConfig {
|
||||||
pub build_updater: fn() -> Result<Box<dyn ReleaseUpdate>>,
|
pub build_updater: fn() -> Result<Box<dyn ReleaseUpdate>>,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use alloc::{
|
|||||||
};
|
};
|
||||||
use core::{fmt, num::NonZeroU32};
|
use core::{fmt, num::NonZeroU32};
|
||||||
|
|
||||||
use flagset::{flags, FlagSet};
|
use flagset::{FlagSet, flags};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{Arch, ArchDummy},
|
arch::{Arch, ArchDummy},
|
||||||
|
|||||||
@@ -6,16 +6,16 @@ use alloc::{
|
|||||||
};
|
};
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
|
|
||||||
use anyhow::{bail, ensure, Context, Result};
|
use anyhow::{Context, Result, anyhow, bail, ensure};
|
||||||
use object::{Object as _, ObjectSection as _, ObjectSymbol as _};
|
use object::{Object as _, ObjectSection as _, ObjectSymbol as _};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{new_arch, Arch},
|
arch::{Arch, new_arch},
|
||||||
diff::DiffObjConfig,
|
diff::DiffObjConfig,
|
||||||
obj::{
|
obj::{
|
||||||
split_meta::{SplitMeta, SPLITMETA_SECTION},
|
|
||||||
Object, Relocation, RelocationFlags, Section, SectionData, SectionFlag, SectionKind,
|
Object, Relocation, RelocationFlags, Section, SectionData, SectionFlag, SectionKind,
|
||||||
Symbol, SymbolFlag, SymbolKind,
|
Symbol, SymbolFlag, SymbolKind,
|
||||||
|
split_meta::{SPLITMETA_SECTION, SplitMeta},
|
||||||
},
|
},
|
||||||
util::{read_u16, read_u32},
|
util::{read_u16, read_u32},
|
||||||
};
|
};
|
||||||
@@ -421,6 +421,44 @@ fn map_relocations(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn calculate_pooled_relocations(
|
||||||
|
arch: &dyn Arch,
|
||||||
|
sections: &mut [Section],
|
||||||
|
symbols: &[Symbol],
|
||||||
|
) -> Result<()> {
|
||||||
|
for (section_index, section) in sections.iter_mut().enumerate() {
|
||||||
|
if section.kind != SectionKind::Code {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut fake_pool_relocs = Vec::new();
|
||||||
|
for symbol in symbols {
|
||||||
|
if symbol.section != Some(section_index) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if symbol.kind != SymbolKind::Function {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let code =
|
||||||
|
section.data_range(symbol.address, symbol.size as usize).ok_or_else(|| {
|
||||||
|
anyhow!(
|
||||||
|
"Symbol data out of bounds: {:#x}..{:#x}",
|
||||||
|
symbol.address,
|
||||||
|
symbol.address + symbol.size
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
fake_pool_relocs.append(&mut arch.generate_pooled_relocations(
|
||||||
|
symbol.address,
|
||||||
|
code,
|
||||||
|
§ion.relocations,
|
||||||
|
symbols,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
section.relocations.append(&mut fake_pool_relocs);
|
||||||
|
section.relocations.sort_by_key(|r| r.address);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_line_info(
|
fn parse_line_info(
|
||||||
obj_file: &object::File,
|
obj_file: &object::File,
|
||||||
sections: &mut [Section],
|
sections: &mut [Section],
|
||||||
@@ -812,6 +850,9 @@ pub fn parse(data: &[u8], config: &DiffObjConfig) -> Result<Object> {
|
|||||||
let (mut symbols, symbol_indices) =
|
let (mut symbols, symbol_indices) =
|
||||||
map_symbols(arch.as_ref(), &obj_file, §ions, §ion_indices, split_meta.as_ref())?;
|
map_symbols(arch.as_ref(), &obj_file, §ions, §ion_indices, split_meta.as_ref())?;
|
||||||
map_relocations(arch.as_ref(), &obj_file, &mut sections, §ion_indices, &symbol_indices)?;
|
map_relocations(arch.as_ref(), &obj_file, &mut sections, §ion_indices, &symbol_indices)?;
|
||||||
|
if config.ppc_calculate_pool_relocations {
|
||||||
|
calculate_pooled_relocations(arch.as_ref(), &mut sections, &symbols)?;
|
||||||
|
}
|
||||||
parse_line_info(&obj_file, &mut sections, §ion_indices, data)?;
|
parse_line_info(&obj_file, &mut sections, §ion_indices, data)?;
|
||||||
if config.combine_data_sections || config.combine_text_sections {
|
if config.combine_data_sections || config.combine_text_sections {
|
||||||
combine_sections(&mut sections, &mut symbols, config)?;
|
combine_sections(&mut sections, &mut symbols, config)?;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use alloc::{string::String, vec, vec::Vec};
|
use alloc::{string::String, vec, vec::Vec};
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{Result, anyhow};
|
||||||
use object::{elf::SHT_NOTE, Endian, ObjectSection};
|
use object::{Endian, ObjectSection, elf::SHT_NOTE};
|
||||||
|
|
||||||
pub const SPLITMETA_SECTION: &str = ".note.split";
|
pub const SPLITMETA_SECTION: &str = ".note.split";
|
||||||
pub const SHT_SPLITMETA: u32 = SHT_NOTE;
|
pub const SHT_SPLITMETA: u32 = SHT_NOTE;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use alloc::format;
|
use alloc::format;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
use anyhow::{ensure, Result};
|
use anyhow::{Result, ensure};
|
||||||
use num_traits::PrimInt;
|
use num_traits::PrimInt;
|
||||||
use object::{Endian, Object};
|
use object::{Endian, Object};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use objdiff_core::{
|
use objdiff_core::{
|
||||||
diff::{display::DiffTextSegment, DiffObjConfig, SymbolDiff},
|
diff::{DiffObjConfig, SymbolDiff, display::DiffTextSegment},
|
||||||
obj::Object,
|
obj::Object,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: objdiff-core/tests/arch_ppc.rs
|
source: objdiff-core/tests/arch_ppc.rs
|
||||||
|
assertion_line: 70
|
||||||
expression: sections_display
|
expression: sections_display
|
||||||
---
|
---
|
||||||
[
|
[
|
||||||
@@ -46,7 +47,7 @@ expression: sections_display
|
|||||||
name: ".text",
|
name: ".text",
|
||||||
size: 3060,
|
size: 3060,
|
||||||
match_percent: Some(
|
match_percent: Some(
|
||||||
59.02353,
|
58.662746,
|
||||||
),
|
),
|
||||||
symbols: [
|
symbols: [
|
||||||
SectionDisplaySymbol {
|
SectionDisplaySymbol {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: objdiff-core/tests/arch_ppc.rs
|
source: objdiff-core/tests/arch_ppc.rs
|
||||||
|
assertion_line: 20
|
||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
[(Address(0), Normal, 5), (Spacing(4), Normal, 0), (Opcode("srwi", 60), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("24")), Normal, 0), (Eol, Normal, 0)]
|
[(Address(0), Normal, 5), (Spacing(4), Normal, 0), (Opcode("srwi", 60), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("24")), Normal, 0), (Eol, Normal, 0)]
|
||||||
@@ -9,7 +10,7 @@ expression: output
|
|||||||
[(Address(16), Normal, 5), (Spacing(4), Normal, 0), (Opcode("b", 45), Normal, 10), (BranchDest(32), Normal, 0), (Basic(" ~>"), Rotating(1), 0), (Eol, Normal, 0)]
|
[(Address(16), Normal, 5), (Spacing(4), Normal, 0), (Opcode("b", 45), Normal, 10), (BranchDest(32), Normal, 0), (Basic(" ~>"), Rotating(1), 0), (Eol, Normal, 0)]
|
||||||
[(Address(20), Normal, 5), (Basic(" ~> "), Rotating(0), 0), (Opcode("lis", 42), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@ha"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(20), Normal, 5), (Basic(" ~> "), Rotating(0), 0), (Opcode("lis", 42), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@ha"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(24), Normal, 5), (Spacing(4), Normal, 0), (Opcode("addi", 41), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@l"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(24), Normal, 5), (Spacing(4), Normal, 0), (Opcode("addi", 41), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@l"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(28), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Eol, Normal, 0)]
|
[(Address(28), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(32), Normal, 5), (Basic(" ~> "), Rotating(1), 0), (Opcode("extrwi", 60), Normal, 10), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("8")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("8")), Normal, 0), (Eol, Normal, 0)]
|
[(Address(32), Normal, 5), (Basic(" ~> "), Rotating(1), 0), (Opcode("extrwi", 60), Normal, 10), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("8")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("8")), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(36), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "text$52", demangled_name: None, address: 8, size: 5, kind: Object, section: Some(2), flags: FlagSet(Local), align: None, virtual_address: Some(2153420056) }), Bright, 0), (Basic("@sda21"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(36), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "text$52", demangled_name: None, address: 8, size: 5, kind: Object, section: Some(2), flags: FlagSet(Local), align: None, virtual_address: Some(2153420056) }), Bright, 0), (Basic("@sda21"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(40), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmpwi", 38), Normal, 10), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(-1)), Normal, 0), (Eol, Normal, 0)]
|
[(Address(40), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmpwi", 38), Normal, 10), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(-1)), Normal, 0), (Eol, Normal, 0)]
|
||||||
@@ -18,7 +19,7 @@ expression: output
|
|||||||
[(Address(52), Normal, 5), (Spacing(4), Normal, 0), (Opcode("b", 45), Normal, 10), (BranchDest(68), Normal, 0), (Basic(" ~>"), Rotating(3), 0), (Eol, Normal, 0)]
|
[(Address(52), Normal, 5), (Spacing(4), Normal, 0), (Opcode("b", 45), Normal, 10), (BranchDest(68), Normal, 0), (Basic(" ~>"), Rotating(3), 0), (Eol, Normal, 0)]
|
||||||
[(Address(56), Normal, 5), (Basic(" ~> "), Rotating(2), 0), (Opcode("lis", 42), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@ha"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(56), Normal, 5), (Basic(" ~> "), Rotating(2), 0), (Opcode("lis", 42), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@ha"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(60), Normal, 5), (Spacing(4), Normal, 0), (Opcode("addi", 41), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@l"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(60), Normal, 5), (Spacing(4), Normal, 0), (Opcode("addi", 41), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@l"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(64), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Eol, Normal, 0)]
|
[(Address(64), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(68), Normal, 5), (Basic(" ~> "), Rotating(3), 0), (Opcode("extrwi", 60), Normal, 10), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("8")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("16")), Normal, 0), (Eol, Normal, 0)]
|
[(Address(68), Normal, 5), (Basic(" ~> "), Rotating(3), 0), (Opcode("extrwi", 60), Normal, 10), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("8")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("16")), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(72), Normal, 5), (Spacing(4), Normal, 0), (Opcode("li", 41), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "text$52", demangled_name: None, address: 8, size: 5, kind: Object, section: Some(2), flags: FlagSet(Local), align: None, virtual_address: Some(2153420056) }), Bright, 0), (Basic("@sda21"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(72), Normal, 5), (Spacing(4), Normal, 0), (Opcode("li", 41), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "text$52", demangled_name: None, address: 8, size: 5, kind: Object, section: Some(2), flags: FlagSet(Local), align: None, virtual_address: Some(2153420056) }), Bright, 0), (Basic("@sda21"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(76), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmpwi", 38), Normal, 10), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(-1)), Normal, 0), (Eol, Normal, 0)]
|
[(Address(76), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmpwi", 38), Normal, 10), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(-1)), Normal, 0), (Eol, Normal, 0)]
|
||||||
@@ -28,7 +29,7 @@ expression: output
|
|||||||
[(Address(92), Normal, 5), (Spacing(4), Normal, 0), (Opcode("b", 45), Normal, 10), (BranchDest(108), Normal, 0), (Basic(" ~>"), Rotating(5), 0), (Eol, Normal, 0)]
|
[(Address(92), Normal, 5), (Spacing(4), Normal, 0), (Opcode("b", 45), Normal, 10), (BranchDest(108), Normal, 0), (Basic(" ~>"), Rotating(5), 0), (Eol, Normal, 0)]
|
||||||
[(Address(96), Normal, 5), (Basic(" ~> "), Rotating(4), 0), (Opcode("lis", 42), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@ha"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(96), Normal, 5), (Basic(" ~> "), Rotating(4), 0), (Opcode("lis", 42), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@ha"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(100), Normal, 5), (Spacing(4), Normal, 0), (Opcode("addi", 41), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@l"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(100), Normal, 5), (Spacing(4), Normal, 0), (Opcode("addi", 41), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@l"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(104), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Eol, Normal, 0)]
|
[(Address(104), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(108), Normal, 5), (Basic(" ~> "), Rotating(5), 0), (Opcode("clrlwi", 60), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("24")), Normal, 0), (Eol, Normal, 0)]
|
[(Address(108), Normal, 5), (Basic(" ~> "), Rotating(5), 0), (Opcode("clrlwi", 60), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("24")), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(112), Normal, 5), (Spacing(4), Normal, 0), (Opcode("li", 41), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "text$52", demangled_name: None, address: 8, size: 5, kind: Object, section: Some(2), flags: FlagSet(Local), align: None, virtual_address: Some(2153420056) }), Bright, 0), (Basic("@sda21"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(112), Normal, 5), (Spacing(4), Normal, 0), (Opcode("li", 41), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "text$52", demangled_name: None, address: 8, size: 5, kind: Object, section: Some(2), flags: FlagSet(Local), align: None, virtual_address: Some(2153420056) }), Bright, 0), (Basic("@sda21"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(116), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmpwi", 38), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(-1)), Normal, 0), (Eol, Normal, 0)]
|
[(Address(116), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmpwi", 38), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(-1)), Normal, 0), (Eol, Normal, 0)]
|
||||||
@@ -38,7 +39,7 @@ expression: output
|
|||||||
[(Address(132), Normal, 5), (Spacing(4), Normal, 0), (Opcode("b", 45), Normal, 10), (BranchDest(148), Normal, 0), (Basic(" ~>"), Rotating(7), 0), (Eol, Normal, 0)]
|
[(Address(132), Normal, 5), (Spacing(4), Normal, 0), (Opcode("b", 45), Normal, 10), (BranchDest(148), Normal, 0), (Basic(" ~>"), Rotating(7), 0), (Eol, Normal, 0)]
|
||||||
[(Address(136), Normal, 5), (Basic(" ~> "), Rotating(6), 0), (Opcode("lis", 42), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@ha"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(136), Normal, 5), (Basic(" ~> "), Rotating(6), 0), (Opcode("lis", 42), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@ha"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(140), Normal, 5), (Spacing(4), Normal, 0), (Opcode("addi", 41), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@l"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(140), Normal, 5), (Spacing(4), Normal, 0), (Opcode("addi", 41), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@l"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(144), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Eol, Normal, 0)]
|
[(Address(144), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(148), Normal, 5), (Basic(" ~> "), Rotating(7), 0), (Opcode("li", 41), Normal, 10), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "text$52", demangled_name: None, address: 8, size: 5, kind: Object, section: Some(2), flags: FlagSet(Local), align: None, virtual_address: Some(2153420056) }), Bright, 0), (Basic("@sda21"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(148), Normal, 5), (Basic(" ~> "), Rotating(7), 0), (Opcode("li", 41), Normal, 10), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "text$52", demangled_name: None, address: 8, size: 5, kind: Object, section: Some(2), flags: FlagSet(Local), align: None, virtual_address: Some(2153420056) }), Bright, 0), (Basic("@sda21"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(152), Normal, 5), (Spacing(4), Normal, 0), (Opcode("li", 41), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(0)), Normal, 0), (Eol, Normal, 0)]
|
[(Address(152), Normal, 5), (Spacing(4), Normal, 0), (Opcode("li", 41), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(0)), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(156), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(3)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(156), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(3)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
|
||||||
@@ -47,22 +48,22 @@ expression: output
|
|||||||
[(Address(168), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(4)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(168), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(4)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(172), Normal, 5), (Spacing(4), Normal, 0), (Opcode("li", 41), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(45)), Normal, 0), (Eol, Normal, 0)]
|
[(Address(172), Normal, 5), (Spacing(4), Normal, 0), (Opcode("li", 41), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(45)), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(176), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbz", 162), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "text$52", demangled_name: None, address: 8, size: 5, kind: Object, section: Some(2), flags: FlagSet(Local), align: None, virtual_address: Some(2153420056) }), Bright, 0), (Basic("@sda21"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(176), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbz", 162), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "text$52", demangled_name: None, address: 8, size: 5, kind: Object, section: Some(2), flags: FlagSet(Local), align: None, virtual_address: Some(2153420056) }), Bright, 0), (Basic("@sda21"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(180), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Eol, Normal, 0)]
|
[(Address(180), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "__ctype_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(184), Normal, 5), (Spacing(4), Normal, 0), (Opcode("andi.", 66), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Unsigned(220)), Normal, 0), (Eol, Normal, 0)]
|
[(Address(184), Normal, 5), (Spacing(4), Normal, 0), (Opcode("andi.", 66), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Unsigned(220)), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(188), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 43), Normal, 10), (BranchDest(196), Normal, 0), (Basic(" ~>"), Rotating(8), 0), (Eol, Normal, 0)]
|
[(Address(188), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 43), Normal, 10), (BranchDest(196), Normal, 0), (Basic(" ~>"), Rotating(8), 0), (Eol, Normal, 0)]
|
||||||
[(Address(192), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(192), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(196), Normal, 5), (Basic(" ~> "), Rotating(8), 0), (Opcode("lbzu", 163), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(1)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(196), Normal, 5), (Basic(" ~> "), Rotating(8), 0), (Opcode("lbzu", 163), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(1)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(200), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Eol, Normal, 0)]
|
[(Address(200), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "__ctype_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(204), Normal, 5), (Spacing(4), Normal, 0), (Opcode("andi.", 66), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Unsigned(220)), Normal, 0), (Eol, Normal, 0)]
|
[(Address(204), Normal, 5), (Spacing(4), Normal, 0), (Opcode("andi.", 66), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Unsigned(220)), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(208), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 43), Normal, 10), (BranchDest(216), Normal, 0), (Basic(" ~>"), Rotating(9), 0), (Eol, Normal, 0)]
|
[(Address(208), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 43), Normal, 10), (BranchDest(216), Normal, 0), (Basic(" ~>"), Rotating(9), 0), (Eol, Normal, 0)]
|
||||||
[(Address(212), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(212), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(216), Normal, 5), (Basic(" ~> "), Rotating(9), 0), (Opcode("lbzu", 163), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(1)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(216), Normal, 5), (Basic(" ~> "), Rotating(9), 0), (Opcode("lbzu", 163), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(1)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(220), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Eol, Normal, 0)]
|
[(Address(220), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "__ctype_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(224), Normal, 5), (Spacing(4), Normal, 0), (Opcode("andi.", 66), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Unsigned(220)), Normal, 0), (Eol, Normal, 0)]
|
[(Address(224), Normal, 5), (Spacing(4), Normal, 0), (Opcode("andi.", 66), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Unsigned(220)), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(228), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 43), Normal, 10), (BranchDest(236), Normal, 0), (Basic(" ~>"), Rotating(10), 0), (Eol, Normal, 0)]
|
[(Address(228), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 43), Normal, 10), (BranchDest(236), Normal, 0), (Basic(" ~>"), Rotating(10), 0), (Eol, Normal, 0)]
|
||||||
[(Address(232), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(232), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(236), Normal, 5), (Basic(" ~> "), Rotating(10), 0), (Opcode("lbzu", 163), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(1)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(236), Normal, 5), (Basic(" ~> "), Rotating(10), 0), (Opcode("lbzu", 163), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(1)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(240), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Eol, Normal, 0)]
|
[(Address(240), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "__ctype_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(244), Normal, 5), (Spacing(4), Normal, 0), (Opcode("andi.", 66), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Unsigned(220)), Normal, 0), (Eol, Normal, 0)]
|
[(Address(244), Normal, 5), (Spacing(4), Normal, 0), (Opcode("andi.", 66), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Unsigned(220)), Normal, 0), (Eol, Normal, 0)]
|
||||||
[(Address(248), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 43), Normal, 10), (BranchDest(256), Normal, 0), (Basic(" ~>"), Rotating(11), 0), (Eol, Normal, 0)]
|
[(Address(248), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 43), Normal, 10), (BranchDest(256), Normal, 0), (Basic(" ~>"), Rotating(11), 0), (Eol, Normal, 0)]
|
||||||
[(Address(252), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
|
[(Address(252), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: objdiff-core/tests/arch_ppc.rs
|
source: objdiff-core/tests/arch_ppc.rs
|
||||||
|
assertion_line: 14
|
||||||
expression: obj
|
expression: obj
|
||||||
---
|
---
|
||||||
Object {
|
Object {
|
||||||
@@ -183,6 +184,14 @@ Object {
|
|||||||
target_symbol: 8,
|
target_symbol: 8,
|
||||||
addend: 0,
|
addend: 0,
|
||||||
},
|
},
|
||||||
|
Relocation {
|
||||||
|
flags: Elf(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
address: 28,
|
||||||
|
target_symbol: 8,
|
||||||
|
addend: 0,
|
||||||
|
},
|
||||||
Relocation {
|
Relocation {
|
||||||
flags: Elf(
|
flags: Elf(
|
||||||
109,
|
109,
|
||||||
@@ -207,6 +216,14 @@ Object {
|
|||||||
target_symbol: 8,
|
target_symbol: 8,
|
||||||
addend: 0,
|
addend: 0,
|
||||||
},
|
},
|
||||||
|
Relocation {
|
||||||
|
flags: Elf(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
address: 64,
|
||||||
|
target_symbol: 8,
|
||||||
|
addend: 0,
|
||||||
|
},
|
||||||
Relocation {
|
Relocation {
|
||||||
flags: Elf(
|
flags: Elf(
|
||||||
109,
|
109,
|
||||||
@@ -231,6 +248,14 @@ Object {
|
|||||||
target_symbol: 8,
|
target_symbol: 8,
|
||||||
addend: 0,
|
addend: 0,
|
||||||
},
|
},
|
||||||
|
Relocation {
|
||||||
|
flags: Elf(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
address: 104,
|
||||||
|
target_symbol: 8,
|
||||||
|
addend: 0,
|
||||||
|
},
|
||||||
Relocation {
|
Relocation {
|
||||||
flags: Elf(
|
flags: Elf(
|
||||||
109,
|
109,
|
||||||
@@ -255,6 +280,14 @@ Object {
|
|||||||
target_symbol: 8,
|
target_symbol: 8,
|
||||||
addend: 0,
|
addend: 0,
|
||||||
},
|
},
|
||||||
|
Relocation {
|
||||||
|
flags: Elf(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
address: 144,
|
||||||
|
target_symbol: 8,
|
||||||
|
addend: 0,
|
||||||
|
},
|
||||||
Relocation {
|
Relocation {
|
||||||
flags: Elf(
|
flags: Elf(
|
||||||
109,
|
109,
|
||||||
@@ -287,6 +320,38 @@ Object {
|
|||||||
target_symbol: 5,
|
target_symbol: 5,
|
||||||
addend: 0,
|
addend: 0,
|
||||||
},
|
},
|
||||||
|
Relocation {
|
||||||
|
flags: Elf(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
address: 180,
|
||||||
|
target_symbol: 9,
|
||||||
|
addend: 0,
|
||||||
|
},
|
||||||
|
Relocation {
|
||||||
|
flags: Elf(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
address: 200,
|
||||||
|
target_symbol: 9,
|
||||||
|
addend: 0,
|
||||||
|
},
|
||||||
|
Relocation {
|
||||||
|
flags: Elf(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
address: 220,
|
||||||
|
target_symbol: 9,
|
||||||
|
addend: 0,
|
||||||
|
},
|
||||||
|
Relocation {
|
||||||
|
flags: Elf(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
address: 240,
|
||||||
|
target_symbol: 9,
|
||||||
|
addend: 0,
|
||||||
|
},
|
||||||
Relocation {
|
Relocation {
|
||||||
flags: Elf(
|
flags: Elf(
|
||||||
109,
|
109,
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ anyhow = "1.0"
|
|||||||
cfg-if = "1.0"
|
cfg-if = "1.0"
|
||||||
const_format = "0.2"
|
const_format = "0.2"
|
||||||
cwdemangle = "1.0"
|
cwdemangle = "1.0"
|
||||||
cwextab = { version = "1.0", git = "https://github.com/CelestialAmber/cwextab.git" }
|
|
||||||
dirs = "6.0"
|
dirs = "6.0"
|
||||||
egui = "0.31"
|
egui = "0.31"
|
||||||
egui_extras = "0.31"
|
egui_extras = "0.31"
|
||||||
@@ -46,8 +45,6 @@ rfd = { version = "0.15" } #, default-features = false, features = ['xdg-portal'
|
|||||||
rlwinmdec = { version = "1.0", git = "https://github.com/CelestialAmber/rlwinmdec.git" }
|
rlwinmdec = { version = "1.0", git = "https://github.com/CelestialAmber/rlwinmdec.git" }
|
||||||
ron = "0.8"
|
ron = "0.8"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
|
||||||
shell-escape = "0.1"
|
|
||||||
time = { version = "0.3", features = ["formatting", "local-offset"] }
|
time = { version = "0.3", features = ["formatting", "local-offset"] }
|
||||||
typed-path = "0.10"
|
typed-path = "0.10"
|
||||||
winit = { version = "0.30", features = ["wayland-csd-adwaita"] }
|
winit = { version = "0.30", features = ["wayland-csd-adwaita"] }
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ use std::{
|
|||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicBool, Ordering},
|
|
||||||
Arc, Mutex, RwLock,
|
Arc, Mutex, RwLock,
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
},
|
},
|
||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
@@ -14,11 +14,11 @@ use std::{
|
|||||||
use filetime::FileTime;
|
use filetime::FileTime;
|
||||||
use globset::Glob;
|
use globset::Glob;
|
||||||
use objdiff_core::{
|
use objdiff_core::{
|
||||||
build::watcher::{create_watcher, Watcher},
|
build::watcher::{Watcher, create_watcher},
|
||||||
config::{
|
config::{
|
||||||
|
DEFAULT_WATCH_PATTERNS, ProjectConfig, ProjectConfigInfo, ProjectObject, ScratchConfig,
|
||||||
build_globset, default_watch_patterns, path::platform_path_serde_option,
|
build_globset, default_watch_patterns, path::platform_path_serde_option,
|
||||||
save_project_config, ProjectConfig, ProjectConfigInfo, ProjectObject, ScratchConfig,
|
save_project_config,
|
||||||
DEFAULT_WATCH_PATTERNS,
|
|
||||||
},
|
},
|
||||||
diff::DiffObjConfig,
|
diff::DiffObjConfig,
|
||||||
jobs::{Job, JobQueue, JobResult},
|
jobs::{Job, JobQueue, JobResult},
|
||||||
@@ -27,22 +27,22 @@ use time::UtcOffset;
|
|||||||
use typed_path::{Utf8PlatformPath, Utf8PlatformPathBuf};
|
use typed_path::{Utf8PlatformPath, Utf8PlatformPathBuf};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app_config::{deserialize_config, AppConfigVersion},
|
app_config::{AppConfigVersion, deserialize_config},
|
||||||
config::{load_project_config, ProjectObjectNode},
|
config::{ProjectObjectNode, load_project_config},
|
||||||
jobs::{create_objdiff_config, egui_waker, start_build},
|
jobs::{create_objdiff_config, egui_waker, start_build},
|
||||||
views::{
|
views::{
|
||||||
appearance::{appearance_window, Appearance},
|
appearance::{Appearance, appearance_window},
|
||||||
config::{
|
config::{
|
||||||
arch_config_window, config_ui, general_config_ui, project_window, ConfigViewState,
|
CONFIG_DISABLED_TEXT, ConfigViewState, arch_config_window, config_ui,
|
||||||
CONFIG_DISABLED_TEXT,
|
general_config_ui, project_window,
|
||||||
},
|
},
|
||||||
debug::debug_window,
|
debug::debug_window,
|
||||||
demangle::{demangle_window, DemangleViewState},
|
demangle::{DemangleViewState, demangle_window},
|
||||||
diff::diff_view_ui,
|
diff::diff_view_ui,
|
||||||
frame_history::FrameHistory,
|
frame_history::FrameHistory,
|
||||||
graphics::{graphics_window, GraphicsConfig, GraphicsViewState},
|
graphics::{GraphicsConfig, GraphicsViewState, graphics_window},
|
||||||
jobs::{jobs_menu_ui, jobs_window},
|
jobs::{jobs_menu_ui, jobs_window},
|
||||||
rlwinm::{rlwinm_decode_window, RlwinmDecodeViewState},
|
rlwinm::{RlwinmDecodeViewState, rlwinm_decode_window},
|
||||||
symbol_diff::{DiffViewAction, DiffViewState, ResolvedNavigation, View},
|
symbol_diff::{DiffViewAction, DiffViewState, ResolvedNavigation, View},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use objdiff_core::{
|
|||||||
};
|
};
|
||||||
use typed_path::{Utf8PlatformPathBuf, Utf8UnixPathBuf};
|
use typed_path::{Utf8PlatformPathBuf, Utf8UnixPathBuf};
|
||||||
|
|
||||||
use crate::app::{AppConfig, ObjectConfig, CONFIG_KEY};
|
use crate::app::{AppConfig, CONFIG_KEY, ObjectConfig};
|
||||||
|
|
||||||
#[derive(Clone, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, serde::Deserialize, serde::Serialize)]
|
||||||
pub struct AppConfigVersion {
|
pub struct AppConfigVersion {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use globset::Glob;
|
use globset::Glob;
|
||||||
use objdiff_core::config::{try_project_config, DEFAULT_WATCH_PATTERNS};
|
use objdiff_core::config::{DEFAULT_WATCH_PATTERNS, try_project_config};
|
||||||
use typed_path::{Utf8UnixComponent, Utf8UnixPath};
|
use typed_path::{Utf8UnixComponent, Utf8UnixPath};
|
||||||
|
|
||||||
use crate::app::{AppState, ObjectConfig};
|
use crate::app::{AppState, ObjectConfig};
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ pub fn load_font_if_needed(
|
|||||||
// FIXME clean up
|
// FIXME clean up
|
||||||
let default_font_ref = family.fonts.get(family.default_index).unwrap();
|
let default_font_ref = family.fonts.get(family.default_index).unwrap();
|
||||||
let default_font = family.handles.get(family.default_index).unwrap();
|
let default_font = family.handles.get(family.default_index).unwrap();
|
||||||
let default_font_data = load_font(default_font).unwrap();
|
let default_font_data = load_font(default_font)?;
|
||||||
log::info!("Loaded font family '{}'", family.family_name);
|
log::info!("Loaded font family '{}'", family.family_name);
|
||||||
fonts.font_data.insert(default_font_ref.full_name(), Arc::new(default_font_data.font_data));
|
fonts.font_data.insert(default_font_ref.full_name(), Arc::new(default_font_data.font_data));
|
||||||
fonts
|
fonts
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use egui::{
|
use egui::{
|
||||||
style::ScrollAnimation, vec2, Context, Key, KeyboardShortcut, Modifiers, PointerButton,
|
Context, Key, KeyboardShortcut, Modifiers, PointerButton, style::ScrollAnimation, vec2,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn any_widget_focused(ctx: &Context) -> bool { ctx.memory(|mem| mem.focused().is_some()) }
|
fn any_widget_focused(ctx: &Context) -> bool { ctx.memory(|mem| mem.focused().is_some()) }
|
||||||
|
|||||||
@@ -3,18 +3,18 @@ use std::{
|
|||||||
task::{Wake, Waker},
|
task::{Wake, Waker},
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{Result, bail};
|
||||||
use jobs::create_scratch;
|
use jobs::create_scratch;
|
||||||
use objdiff_core::{
|
use objdiff_core::{
|
||||||
build::BuildConfig,
|
build::BuildConfig,
|
||||||
diff::MappingConfig,
|
diff::MappingConfig,
|
||||||
jobs,
|
jobs,
|
||||||
jobs::{check_update::CheckUpdateConfig, objdiff, update::UpdateConfig, Job, JobQueue},
|
jobs::{Job, JobQueue, check_update::CheckUpdateConfig, objdiff, update::UpdateConfig},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::{AppConfig, AppState},
|
app::{AppConfig, AppState},
|
||||||
update::{build_updater, BIN_NAME_NEW, BIN_NAME_OLD},
|
update::{BIN_NAME_NEW, BIN_NAME_OLD, build_updater},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EguiWaker(egui::Context);
|
struct EguiWaker(egui::Context);
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ use std::{
|
|||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{ensure, Result};
|
use anyhow::{Result, ensure};
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use time::UtcOffset;
|
use time::UtcOffset;
|
||||||
use tracing_subscriber::EnvFilter;
|
use tracing_subscriber::EnvFilter;
|
||||||
|
|
||||||
use crate::views::graphics::{load_graphics_config, GraphicsBackend, GraphicsConfig};
|
use crate::views::graphics::{GraphicsBackend, GraphicsConfig, load_graphics_config};
|
||||||
|
|
||||||
fn load_icon() -> Result<egui::IconData> {
|
fn load_icon() -> Result<egui::IconData> {
|
||||||
let decoder = png::Decoder::new(include_bytes!("../assets/icon_64.png").as_ref());
|
let decoder = png::Decoder::new(include_bytes!("../assets/icon_64.png").as_ref());
|
||||||
@@ -86,7 +86,7 @@ fn main() -> ExitCode {
|
|||||||
}
|
}
|
||||||
#[cfg(feature = "wgpu")]
|
#[cfg(feature = "wgpu")]
|
||||||
{
|
{
|
||||||
use eframe::egui_wgpu::{wgpu, WgpuSetup};
|
use eframe::egui_wgpu::{WgpuSetup, wgpu};
|
||||||
if graphics_config.desired_backend.is_supported() {
|
if graphics_config.desired_backend.is_supported() {
|
||||||
native_options.wgpu_options.wgpu_setup = match native_options.wgpu_options.wgpu_setup {
|
native_options.wgpu_options.wgpu_setup = match native_options.wgpu_options.wgpu_setup {
|
||||||
WgpuSetup::CreateNew(mut setup) => {
|
WgpuSetup::CreateNew(mut setup) => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use egui::{text::LayoutJob, Color32, FontFamily, FontId, TextFormat, TextStyle, Widget};
|
use egui::{Color32, FontFamily, FontId, TextFormat, TextStyle, Widget, text::LayoutJob};
|
||||||
use time::UtcOffset;
|
use time::UtcOffset;
|
||||||
|
|
||||||
use crate::fonts::load_font_if_needed;
|
use crate::fonts::load_font_if_needed;
|
||||||
|
|||||||
@@ -5,17 +5,17 @@ use std::{mem::take, path::MAIN_SEPARATOR};
|
|||||||
#[cfg(all(windows, feature = "wsl"))]
|
#[cfg(all(windows, feature = "wsl"))]
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use egui::{
|
use egui::{
|
||||||
output::OpenUrl, text::LayoutJob, CollapsingHeader, FontFamily, FontId, RichText,
|
CollapsingHeader, FontFamily, FontId, RichText, SelectableLabel, TextFormat, Widget,
|
||||||
SelectableLabel, TextFormat, Widget,
|
output::OpenUrl, text::LayoutJob,
|
||||||
};
|
};
|
||||||
use globset::Glob;
|
use globset::Glob;
|
||||||
use objdiff_core::{
|
use objdiff_core::{
|
||||||
config::{path::check_path_buf, DEFAULT_WATCH_PATTERNS},
|
config::{DEFAULT_WATCH_PATTERNS, path::check_path_buf},
|
||||||
diff::{
|
diff::{
|
||||||
ConfigEnum, ConfigEnumVariantInfo, ConfigPropertyId, ConfigPropertyKind,
|
CONFIG_GROUPS, ConfigEnum, ConfigEnumVariantInfo, ConfigPropertyId, ConfigPropertyKind,
|
||||||
ConfigPropertyValue, CONFIG_GROUPS,
|
ConfigPropertyValue,
|
||||||
},
|
},
|
||||||
jobs::{check_update::CheckUpdateResult, Job, JobQueue, JobResult},
|
jobs::{Job, JobQueue, JobResult, check_update::CheckUpdateResult},
|
||||||
};
|
};
|
||||||
use typed_path::Utf8PlatformPathBuf;
|
use typed_path::Utf8PlatformPathBuf;
|
||||||
|
|
||||||
@@ -347,11 +347,7 @@ fn display_unit(
|
|||||||
let color = if selected {
|
let color = if selected {
|
||||||
appearance.emphasized_text_color
|
appearance.emphasized_text_color
|
||||||
} else if let Some(complete) = object.complete {
|
} else if let Some(complete) = object.complete {
|
||||||
if complete {
|
if complete { appearance.insert_color } else { appearance.delete_color }
|
||||||
appearance.insert_color
|
|
||||||
} else {
|
|
||||||
appearance.delete_color
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
appearance.text_color
|
appearance.text_color
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
use std::{cmp::min, default::Default, mem::take};
|
use std::{cmp::min, default::Default, mem::take};
|
||||||
|
|
||||||
use egui::{text::LayoutJob, Label, Sense, Widget};
|
use egui::{Label, Sense, Widget, text::LayoutJob};
|
||||||
use objdiff_core::{
|
use objdiff_core::{
|
||||||
diff::{
|
diff::{
|
||||||
data::resolve_relocation,
|
|
||||||
display::{relocation_context, relocation_hover, ContextItem, HoverItem},
|
|
||||||
DataDiff, DataDiffKind, DataRelocationDiff,
|
DataDiff, DataDiffKind, DataRelocationDiff,
|
||||||
|
data::resolve_relocation,
|
||||||
|
display::{ContextItem, HoverItem, relocation_context, relocation_hover},
|
||||||
},
|
},
|
||||||
obj::Object,
|
obj::Object,
|
||||||
};
|
};
|
||||||
@@ -32,7 +32,7 @@ fn data_row_hover(obj: &Object, diffs: &[(DataDiff, Vec<DataRelocationDiff>)]) -
|
|||||||
// TODO: Change hover text color depending on Insert/Delete/Replace kind
|
// TODO: Change hover text color depending on Insert/Delete/Replace kind
|
||||||
// let color = get_color_for_diff_kind(reloc_diff.kind, appearance);
|
// let color = get_color_for_diff_kind(reloc_diff.kind, appearance);
|
||||||
|
|
||||||
let reloc = resolve_relocation(obj, reloc);
|
let reloc = resolve_relocation(&obj.symbols, reloc);
|
||||||
out.append(&mut relocation_hover(obj, reloc));
|
out.append(&mut relocation_hover(obj, reloc));
|
||||||
}
|
}
|
||||||
out
|
out
|
||||||
@@ -55,7 +55,7 @@ fn data_row_context(
|
|||||||
}
|
}
|
||||||
prev_reloc = Some(reloc);
|
prev_reloc = Some(reloc);
|
||||||
|
|
||||||
let reloc = resolve_relocation(obj, reloc);
|
let reloc = resolve_relocation(&obj.symbols, reloc);
|
||||||
out.append(&mut relocation_context(obj, reloc, None));
|
out.append(&mut relocation_context(obj, reloc, None));
|
||||||
}
|
}
|
||||||
out
|
out
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use egui::{text::LayoutJob, Id, Layout, RichText, ScrollArea, TextEdit, Ui, Widget};
|
use egui::{Id, Layout, RichText, ScrollArea, TextEdit, Ui, Widget, text::LayoutJob};
|
||||||
use objdiff_core::{
|
use objdiff_core::{
|
||||||
build::BuildStatus,
|
build::BuildStatus,
|
||||||
diff::{
|
diff::{
|
||||||
display::{ContextItem, HoverItem, HoverItemColor, SymbolFilter, SymbolNavigationKind},
|
|
||||||
DiffObjConfig, ObjectDiff, SectionDiff, SymbolDiff,
|
DiffObjConfig, ObjectDiff, SectionDiff, SymbolDiff,
|
||||||
|
display::{ContextItem, HoverItem, HoverItemColor, SymbolFilter, SymbolNavigationKind},
|
||||||
},
|
},
|
||||||
obj::{Object, Section, Symbol},
|
obj::{Object, Section, Symbol},
|
||||||
};
|
};
|
||||||
@@ -14,13 +14,12 @@ use crate::{
|
|||||||
views::{
|
views::{
|
||||||
appearance::Appearance,
|
appearance::Appearance,
|
||||||
column_layout::{render_header, render_strips, render_table},
|
column_layout::{render_header, render_strips, render_table},
|
||||||
data_diff::{data_row_ui, split_diffs, BYTES_PER_ROW},
|
data_diff::{BYTES_PER_ROW, data_row_ui, split_diffs},
|
||||||
extab_diff::extab_ui,
|
extab_diff::extab_ui,
|
||||||
function_diff::{asm_col_ui, FunctionDiffContext},
|
function_diff::{FunctionDiffContext, asm_col_ui},
|
||||||
symbol_diff::{
|
symbol_diff::{
|
||||||
match_color_for_symbol, symbol_context_menu_ui, symbol_hover_ui, symbol_list_ui,
|
|
||||||
DiffViewAction, DiffViewNavigation, DiffViewState, SymbolDiffContext, SymbolRefByName,
|
DiffViewAction, DiffViewNavigation, DiffViewState, SymbolDiffContext, SymbolRefByName,
|
||||||
View,
|
View, match_color_for_symbol, symbol_context_menu_ui, symbol_hover_ui, symbol_list_ui,
|
||||||
},
|
},
|
||||||
write_text,
|
write_text,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
use std::{cmp::Ordering, default::Default};
|
use std::{cmp::Ordering, default::Default};
|
||||||
|
|
||||||
use egui::{text::LayoutJob, Label, Response, Sense, Widget};
|
use egui::{Label, Response, Sense, Widget, text::LayoutJob};
|
||||||
use egui_extras::TableRow;
|
use egui_extras::TableRow;
|
||||||
use objdiff_core::{
|
use objdiff_core::{
|
||||||
diff::{
|
diff::{
|
||||||
display::{
|
|
||||||
display_row, instruction_context, instruction_hover, DiffText, DiffTextColor,
|
|
||||||
DiffTextSegment, HighlightKind,
|
|
||||||
},
|
|
||||||
DiffObjConfig, InstructionDiffKind, InstructionDiffRow, ObjectDiff,
|
DiffObjConfig, InstructionDiffKind, InstructionDiffRow, ObjectDiff,
|
||||||
|
display::{
|
||||||
|
DiffText, DiffTextColor, DiffTextSegment, HighlightKind, display_row,
|
||||||
|
instruction_context, instruction_hover,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
obj::{InstructionArgValue, InstructionRef, Object},
|
obj::{InstructionArgValue, InstructionRef, Object},
|
||||||
util::ReallySigned,
|
util::ReallySigned,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use egui::{text::LayoutJob, Context, FontId, RichText, TextFormat, TextStyle, Window};
|
use egui::{Context, FontId, RichText, TextFormat, TextStyle, Window, text::LayoutJob};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::views::{appearance::Appearance, frame_history::FrameHistory};
|
use crate::views::{appearance::Appearance, frame_history::FrameHistory};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use egui::{text::LayoutJob, Color32, FontId, TextFormat};
|
use egui::{Color32, FontId, TextFormat, text::LayoutJob};
|
||||||
|
|
||||||
pub(crate) mod appearance;
|
pub(crate) mod appearance;
|
||||||
pub(crate) mod column_layout;
|
pub(crate) mod column_layout;
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
use std::mem::take;
|
use std::mem::take;
|
||||||
|
|
||||||
use egui::{
|
use egui::{
|
||||||
style::ScrollAnimation, text::LayoutJob, CollapsingHeader, Color32, Id, OpenUrl, ScrollArea,
|
CollapsingHeader, Color32, Id, OpenUrl, ScrollArea, SelectableLabel, Ui, Widget,
|
||||||
SelectableLabel, Ui, Widget,
|
style::ScrollAnimation, text::LayoutJob,
|
||||||
};
|
};
|
||||||
use objdiff_core::{
|
use objdiff_core::{
|
||||||
diff::{
|
diff::{
|
||||||
display::{
|
|
||||||
display_sections, symbol_context, symbol_hover, HighlightKind, SectionDisplay,
|
|
||||||
SymbolFilter, SymbolNavigationKind,
|
|
||||||
},
|
|
||||||
ObjectDiff, SymbolDiff,
|
ObjectDiff, SymbolDiff,
|
||||||
|
display::{
|
||||||
|
HighlightKind, SectionDisplay, SymbolFilter, SymbolNavigationKind, display_sections,
|
||||||
|
symbol_context, symbol_hover,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
jobs::{create_scratch::CreateScratchResult, objdiff::ObjDiffResult, Job, JobQueue, JobResult},
|
jobs::{Job, JobQueue, JobResult, create_scratch::CreateScratchResult, objdiff::ObjDiffResult},
|
||||||
obj::{Object, Section, SectionKind, Symbol, SymbolFlag},
|
obj::{Object, Section, SectionKind, Symbol, SymbolFlag},
|
||||||
};
|
};
|
||||||
use regex::{Regex, RegexBuilder};
|
use regex::{Regex, RegexBuilder};
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "objdiff-wasm"
|
name = "objdiff-wasm"
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
edition.workspace = true
|
# TODO: Update to 2024
|
||||||
|
# https://github.com/bytecodealliance/wit-bindgen/pull/1183
|
||||||
|
edition = "2021"
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "objdiff-wasm",
|
"name": "objdiff-wasm",
|
||||||
"version": "3.0.0-alpha.3",
|
"version": "3.0.0-beta.1",
|
||||||
"description": "A local diffing tool for decompilation projects.",
|
"description": "A local diffing tool for decompilation projects.",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Luke Street",
|
"name": "Luke Street",
|
||||||
|
|||||||
Reference in New Issue
Block a user