mirror of
https://github.com/encounter/objdiff.git
synced 2025-06-07 15:13:47 +00:00
Diff schema updates & WASM updates
This commit is contained in:
parent
b0c5431ac5
commit
c45f4bbc99
@ -21,9 +21,9 @@ enum SymbolFlag {
|
|||||||
SYMBOL_NONE = 0;
|
SYMBOL_NONE = 0;
|
||||||
SYMBOL_GLOBAL = 1;
|
SYMBOL_GLOBAL = 1;
|
||||||
SYMBOL_LOCAL = 2;
|
SYMBOL_LOCAL = 2;
|
||||||
SYMBOL_WEAK = 3;
|
SYMBOL_WEAK = 4;
|
||||||
SYMBOL_COMMON = 4;
|
SYMBOL_COMMON = 8;
|
||||||
SYMBOL_HIDDEN = 5;
|
SYMBOL_HIDDEN = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A single parsed instruction
|
// A single parsed instruction
|
||||||
@ -122,10 +122,17 @@ message InstructionBranchTo {
|
|||||||
uint32 branch_index = 2;
|
uint32 branch_index = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message FunctionDiff {
|
message SymbolRef {
|
||||||
|
optional uint32 section_index = 1;
|
||||||
|
uint32 symbol_index = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SymbolDiff {
|
||||||
Symbol symbol = 1;
|
Symbol symbol = 1;
|
||||||
repeated InstructionDiff instructions = 2;
|
repeated InstructionDiff instructions = 2;
|
||||||
optional float match_percent = 3;
|
optional float match_percent = 3;
|
||||||
|
// The symbol ref in the _other_ object that this symbol was diffed against
|
||||||
|
optional SymbolRef target = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message DataDiff {
|
message DataDiff {
|
||||||
@ -140,7 +147,7 @@ message SectionDiff {
|
|||||||
SectionKind kind = 2;
|
SectionKind kind = 2;
|
||||||
uint64 size = 3;
|
uint64 size = 3;
|
||||||
uint64 address = 4;
|
uint64 address = 4;
|
||||||
repeated FunctionDiff functions = 5;
|
repeated SymbolDiff symbols = 5;
|
||||||
repeated DataDiff data = 6;
|
repeated DataDiff data = 6;
|
||||||
optional float match_percent = 7;
|
optional float match_percent = 7;
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
@ -4,6 +4,7 @@ use crate::{
|
|||||||
ObjDataDiff, ObjDataDiffKind, ObjDiff, ObjInsArgDiff, ObjInsBranchFrom, ObjInsBranchTo,
|
ObjDataDiff, ObjDataDiffKind, ObjDiff, ObjInsArgDiff, ObjInsBranchFrom, ObjInsBranchTo,
|
||||||
ObjInsDiff, ObjInsDiffKind, ObjSectionDiff, ObjSymbolDiff,
|
ObjInsDiff, ObjInsDiffKind, ObjSectionDiff, ObjSymbolDiff,
|
||||||
},
|
},
|
||||||
|
obj,
|
||||||
obj::{
|
obj::{
|
||||||
ObjInfo, ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSectionKind, ObjSymbol,
|
ObjInfo, ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSectionKind, ObjSymbol,
|
||||||
ObjSymbolFlagSet, ObjSymbolFlags,
|
ObjSymbolFlagSet, ObjSymbolFlags,
|
||||||
@ -39,14 +40,14 @@ impl ObjectDiff {
|
|||||||
impl SectionDiff {
|
impl SectionDiff {
|
||||||
pub fn new(obj: &ObjInfo, section_index: usize, section_diff: &ObjSectionDiff) -> Self {
|
pub fn new(obj: &ObjInfo, section_index: usize, section_diff: &ObjSectionDiff) -> Self {
|
||||||
let section = &obj.sections[section_index];
|
let section = &obj.sections[section_index];
|
||||||
let functions = section_diff.symbols.iter().map(|d| FunctionDiff::new(obj, d)).collect();
|
let symbols = section_diff.symbols.iter().map(|d| SymbolDiff::new(obj, d)).collect();
|
||||||
let data = section_diff.data_diff.iter().map(|d| DataDiff::new(obj, d)).collect();
|
let data = section_diff.data_diff.iter().map(|d| DataDiff::new(obj, d)).collect();
|
||||||
Self {
|
Self {
|
||||||
name: section.name.to_string(),
|
name: section.name.to_string(),
|
||||||
kind: SectionKind::from(section.kind) as i32,
|
kind: SectionKind::from(section.kind) as i32,
|
||||||
size: section.size,
|
size: section.size,
|
||||||
address: section.address,
|
address: section.address,
|
||||||
functions,
|
symbols,
|
||||||
data,
|
data,
|
||||||
match_percent: section_diff.match_percent,
|
match_percent: section_diff.match_percent,
|
||||||
}
|
}
|
||||||
@ -64,13 +65,22 @@ impl From<ObjSectionKind> for SectionKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionDiff {
|
impl From<obj::SymbolRef> for SymbolRef {
|
||||||
|
fn from(value: obj::SymbolRef) -> Self {
|
||||||
|
Self {
|
||||||
|
section_index: if value.section_idx == obj::SECTION_COMMON {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(value.section_idx as u32)
|
||||||
|
},
|
||||||
|
symbol_index: value.symbol_idx as u32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SymbolDiff {
|
||||||
pub fn new(object: &ObjInfo, symbol_diff: &ObjSymbolDiff) -> Self {
|
pub fn new(object: &ObjInfo, symbol_diff: &ObjSymbolDiff) -> Self {
|
||||||
let (_section, symbol) = object.section_symbol(symbol_diff.symbol_ref);
|
let (_section, symbol) = object.section_symbol(symbol_diff.symbol_ref);
|
||||||
// let diff_symbol = symbol_diff.diff_symbol.map(|symbol_ref| {
|
|
||||||
// let (_section, symbol) = object.section_symbol(symbol_ref);
|
|
||||||
// Symbol::from(symbol)
|
|
||||||
// });
|
|
||||||
let instructions = symbol_diff
|
let instructions = symbol_diff
|
||||||
.instructions
|
.instructions
|
||||||
.iter()
|
.iter()
|
||||||
@ -78,9 +88,9 @@ impl FunctionDiff {
|
|||||||
.collect();
|
.collect();
|
||||||
Self {
|
Self {
|
||||||
symbol: Some(Symbol::new(symbol)),
|
symbol: Some(Symbol::new(symbol)),
|
||||||
// diff_symbol,
|
|
||||||
instructions,
|
instructions,
|
||||||
match_percent: symbol_diff.match_percent,
|
match_percent: symbol_diff.match_percent,
|
||||||
|
target: symbol_diff.target_symbol.map(SymbolRef::from),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,7 +120,7 @@ impl Symbol {
|
|||||||
fn symbol_flags(value: ObjSymbolFlagSet) -> u32 {
|
fn symbol_flags(value: ObjSymbolFlagSet) -> u32 {
|
||||||
let mut flags = 0u32;
|
let mut flags = 0u32;
|
||||||
if value.0.contains(ObjSymbolFlags::Global) {
|
if value.0.contains(ObjSymbolFlags::Global) {
|
||||||
flags |= SymbolFlag::SymbolNone as u32;
|
flags |= SymbolFlag::SymbolGlobal as u32;
|
||||||
}
|
}
|
||||||
if value.0.contains(ObjSymbolFlags::Local) {
|
if value.0.contains(ObjSymbolFlags::Local) {
|
||||||
flags |= SymbolFlag::SymbolLocal as u32;
|
flags |= SymbolFlag::SymbolLocal as u32;
|
||||||
|
@ -6,11 +6,11 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use bimap::BiBTreeMap;
|
|
||||||
use filetime::FileTime;
|
use filetime::FileTime;
|
||||||
use globset::{Glob, GlobSet, GlobSetBuilder};
|
use globset::{Glob, GlobSet, GlobSetBuilder};
|
||||||
|
|
||||||
#[derive(Default, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Default, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
|
#[cfg_attr(feature = "wasm", derive(tsify_next::Tsify), tsify(from_wasm_abi))]
|
||||||
pub struct ProjectConfig {
|
pub struct ProjectConfig {
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub min_version: Option<String>,
|
pub min_version: Option<String>,
|
||||||
@ -55,6 +55,7 @@ impl ProjectConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Default, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
|
#[cfg_attr(feature = "wasm", derive(tsify_next::Tsify), tsify(from_wasm_abi))]
|
||||||
pub struct ProjectObject {
|
pub struct ProjectObject {
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
@ -78,9 +79,15 @@ pub struct ProjectObject {
|
|||||||
pub symbol_mappings: Option<SymbolMappings>,
|
pub symbol_mappings: Option<SymbolMappings>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type SymbolMappings = BiBTreeMap<String, String>;
|
#[cfg(feature = "wasm")]
|
||||||
|
#[tsify_next::declare]
|
||||||
|
pub type SymbolMappings = std::collections::BTreeMap<String, String>;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "wasm"))]
|
||||||
|
pub type SymbolMappings = bimap::BiBTreeMap<String, String>;
|
||||||
|
|
||||||
#[derive(Default, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Default, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
|
#[cfg_attr(feature = "wasm", derive(tsify_next::Tsify), tsify(from_wasm_abi))]
|
||||||
pub struct ProjectObjectMetadata {
|
pub struct ProjectObjectMetadata {
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub complete: Option<bool>,
|
pub complete: Option<bool>,
|
||||||
@ -95,6 +102,7 @@ pub struct ProjectObjectMetadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Default, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
|
#[cfg_attr(feature = "wasm", derive(tsify_next::Tsify), tsify(from_wasm_abi))]
|
||||||
pub struct ProjectProgressCategory {
|
pub struct ProjectProgressCategory {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub id: String,
|
pub id: String,
|
||||||
@ -154,6 +162,7 @@ impl ProjectObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
#[derive(Default, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
|
#[cfg_attr(feature = "wasm", derive(tsify_next::Tsify), tsify(from_wasm_abi))]
|
||||||
pub struct ScratchConfig {
|
pub struct ScratchConfig {
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub platform: Option<String>,
|
pub platform: Option<String>,
|
||||||
|
@ -155,8 +155,7 @@ pub enum ArmR9Usage {
|
|||||||
const fn default_true() -> bool { true }
|
const fn default_true() -> bool { true }
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[cfg_attr(feature = "wasm", derive(tsify_next::Tsify))]
|
#[cfg_attr(feature = "wasm", derive(tsify_next::Tsify), tsify(from_wasm_abi))]
|
||||||
#[cfg_attr(feature = "wasm", tsify(from_wasm_abi))]
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct DiffObjConfig {
|
pub struct DiffObjConfig {
|
||||||
pub relax_reloc_diffs: bool,
|
pub relax_reloc_diffs: bool,
|
||||||
@ -637,6 +636,7 @@ struct SectionMatch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, serde::Deserialize, serde::Serialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, serde::Deserialize, serde::Serialize)]
|
||||||
|
#[cfg_attr(feature = "wasm", derive(tsify_next::Tsify), tsify(from_wasm_abi))]
|
||||||
pub struct MappingConfig {
|
pub struct MappingConfig {
|
||||||
/// Manual symbol mappings
|
/// Manual symbol mappings
|
||||||
pub mappings: SymbolMappings,
|
pub mappings: SymbolMappings,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "objdiff-wasm",
|
"name": "objdiff-wasm",
|
||||||
"version": "2.0.0",
|
"version": "2.5.0",
|
||||||
"description": "A local diffing tool for decompilation projects.",
|
"description": "A local diffing tool for decompilation projects.",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Luke Street",
|
"name": "Luke Street",
|
||||||
@ -21,7 +21,7 @@
|
|||||||
"build": "tsup",
|
"build": "tsup",
|
||||||
"build:all": "npm run build:wasm && npm run build:proto && npm run build",
|
"build:all": "npm run build:wasm && npm run build:proto && npm run build",
|
||||||
"build:proto": "protoc --ts_out=gen --ts_opt add_pb_suffix,eslint_disable,ts_nocheck,use_proto_field_name --proto_path=../objdiff-core/protos ../objdiff-core/protos/*.proto",
|
"build:proto": "protoc --ts_out=gen --ts_opt add_pb_suffix,eslint_disable,ts_nocheck,use_proto_field_name --proto_path=../objdiff-core/protos ../objdiff-core/protos/*.proto",
|
||||||
"build:wasm": "cd ../objdiff-core && wasm-pack build --out-dir ../objdiff-wasm/pkg --target web -- --features arm,dwarf,ppc,x86,wasm"
|
"build:wasm": "cd ../objdiff-core && wasm-pack build --out-dir ../objdiff-wasm/pkg --target web -- --features arm,arm64,dwarf,config,ppc,x86,wasm"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@protobuf-ts/runtime": "^2.9.4"
|
"@protobuf-ts/runtime": "^2.9.4"
|
||||||
|
@ -194,12 +194,17 @@ export function displayDiff(diff: InstructionDiff, baseAddr: bigint, cb: (text:
|
|||||||
cb({type: 'spacing', count: 4});
|
cb({type: 'spacing', count: 4});
|
||||||
}
|
}
|
||||||
cb({type: 'opcode', mnemonic: ins.mnemonic, opcode: ins.opcode});
|
cb({type: 'opcode', mnemonic: ins.mnemonic, opcode: ins.opcode});
|
||||||
|
let arg_diff_idx = 0; // non-PlainText argument index
|
||||||
for (let i = 0; i < ins.arguments.length; i++) {
|
for (let i = 0; i < ins.arguments.length; i++) {
|
||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
cb({type: 'spacing', count: 1});
|
cb({type: 'spacing', count: 1});
|
||||||
}
|
}
|
||||||
const arg = ins.arguments[i].value;
|
const arg = ins.arguments[i].value;
|
||||||
const diff_index = diff.arg_diff[i]?.diff_index;
|
let diff_index: number | undefined;
|
||||||
|
if (arg.oneofKind !== 'plain_text') {
|
||||||
|
diff_index = diff.arg_diff[arg_diff_idx]?.diff_index;
|
||||||
|
arg_diff_idx++;
|
||||||
|
}
|
||||||
switch (arg.oneofKind) {
|
switch (arg.oneofKind) {
|
||||||
case "plain_text":
|
case "plain_text":
|
||||||
cb({type: 'basic', text: arg.plain_text, diff_index});
|
cb({type: 'basic', text: arg.plain_text, diff_index});
|
||||||
|
@ -73,12 +73,19 @@ self.onmessage = (event: MessageEvent<InMessage>) => {
|
|||||||
const result = await handler(data as never);
|
const result = await handler(data as never);
|
||||||
const end = performance.now();
|
const end = performance.now();
|
||||||
console.debug(`Worker message ${data.messageId} took ${end - start}ms`);
|
console.debug(`Worker message ${data.messageId} took ${end - start}ms`);
|
||||||
|
let transfer: Transferable[] = [];
|
||||||
|
if (result instanceof Uint8Array) {
|
||||||
|
console.log("Transferring!", result.byteLength);
|
||||||
|
transfer = [result.buffer];
|
||||||
|
} else {
|
||||||
|
console.log("Didn't transfer", typeof result);
|
||||||
|
}
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
type: 'result',
|
type: 'result',
|
||||||
result: result,
|
result: result,
|
||||||
error: null,
|
error: null,
|
||||||
messageId,
|
messageId,
|
||||||
} as OutMessage);
|
} as OutMessage, {transfer});
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`No handler for ${data.type}`);
|
throw new Error(`No handler for ${data.type}`);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user