mirror of
https://github.com/encounter/objdiff.git
synced 2025-12-10 22:17:51 +00:00
Updates & initial MIPS support
This commit is contained in:
@@ -1,85 +1,124 @@
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use crate::{
|
||||
app::{AppConfig, ViewState},
|
||||
jobs::build::queue_build,
|
||||
app::{AppConfig, DiffKind, ViewState},
|
||||
jobs::{bindiff::queue_bindiff, build::queue_build},
|
||||
};
|
||||
|
||||
pub fn config_ui(ui: &mut egui::Ui, config: &Arc<RwLock<AppConfig>>, view_state: &mut ViewState) {
|
||||
let mut config_guard = config.write().unwrap();
|
||||
let AppConfig { project_dir, project_dir_change, build_asm_dir, build_src_dir, build_obj } =
|
||||
&mut *config_guard;
|
||||
let AppConfig {
|
||||
project_dir,
|
||||
project_dir_change,
|
||||
build_asm_dir,
|
||||
build_src_dir,
|
||||
build_obj,
|
||||
left_obj,
|
||||
right_obj,
|
||||
} = &mut *config_guard;
|
||||
|
||||
if ui.button("Select project dir").clicked() {
|
||||
if let Some(path) = rfd::FileDialog::new().pick_folder() {
|
||||
*project_dir = Some(path);
|
||||
*project_dir_change = true;
|
||||
*build_asm_dir = None;
|
||||
*build_src_dir = None;
|
||||
*build_obj = None;
|
||||
}
|
||||
}
|
||||
if let Some(dir) = project_dir {
|
||||
ui.label(dir.to_string_lossy());
|
||||
}
|
||||
|
||||
ui.separator();
|
||||
|
||||
if let Some(project_dir) = project_dir {
|
||||
if ui.button("Select asm build dir").clicked() {
|
||||
if let Some(path) = rfd::FileDialog::new().set_directory(&project_dir).pick_folder() {
|
||||
*build_asm_dir = Some(path);
|
||||
if view_state.diff_kind == DiffKind::SplitObj {
|
||||
if ui.button("Select project dir").clicked() {
|
||||
if let Some(path) = rfd::FileDialog::new().pick_folder() {
|
||||
*project_dir = Some(path);
|
||||
*project_dir_change = true;
|
||||
*build_asm_dir = None;
|
||||
*build_src_dir = None;
|
||||
*build_obj = None;
|
||||
}
|
||||
}
|
||||
if let Some(dir) = build_asm_dir {
|
||||
if let Some(dir) = project_dir {
|
||||
ui.label(dir.to_string_lossy());
|
||||
}
|
||||
|
||||
ui.separator();
|
||||
|
||||
if ui.button("Select src build dir").clicked() {
|
||||
if let Some(path) = rfd::FileDialog::new().set_directory(&project_dir).pick_folder() {
|
||||
*build_src_dir = Some(path);
|
||||
*build_obj = None;
|
||||
if let Some(project_dir) = project_dir {
|
||||
if ui.button("Select asm build dir").clicked() {
|
||||
if let Some(path) = rfd::FileDialog::new().set_directory(&project_dir).pick_folder()
|
||||
{
|
||||
*build_asm_dir = Some(path);
|
||||
*build_obj = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(dir) = build_src_dir {
|
||||
ui.label(dir.to_string_lossy());
|
||||
if let Some(dir) = build_asm_dir {
|
||||
ui.label(dir.to_string_lossy());
|
||||
}
|
||||
|
||||
ui.separator();
|
||||
|
||||
if ui.button("Select src build dir").clicked() {
|
||||
if let Some(path) = rfd::FileDialog::new().set_directory(&project_dir).pick_folder()
|
||||
{
|
||||
*build_src_dir = Some(path);
|
||||
*build_obj = None;
|
||||
}
|
||||
}
|
||||
if let Some(dir) = build_src_dir {
|
||||
ui.label(dir.to_string_lossy());
|
||||
}
|
||||
|
||||
ui.separator();
|
||||
}
|
||||
|
||||
ui.separator();
|
||||
}
|
||||
|
||||
if let Some(build_src_dir) = build_src_dir {
|
||||
if ui.button("Select obj").clicked() {
|
||||
if let Some(path) = rfd::FileDialog::new()
|
||||
.set_directory(&build_src_dir)
|
||||
.add_filter("Object file", &["o"])
|
||||
.pick_file()
|
||||
{
|
||||
let mut new_build_obj: Option<String> = None;
|
||||
if let Ok(obj_path) = path.strip_prefix(&build_src_dir) {
|
||||
new_build_obj = Some(obj_path.display().to_string());
|
||||
} else if let Some(build_asm_dir) = build_asm_dir {
|
||||
if let Ok(obj_path) = path.strip_prefix(&build_asm_dir) {
|
||||
if let Some(build_src_dir) = build_src_dir {
|
||||
if ui.button("Select obj").clicked() {
|
||||
if let Some(path) = rfd::FileDialog::new()
|
||||
.set_directory(&build_src_dir)
|
||||
.add_filter("Object file", &["o", "elf"])
|
||||
.pick_file()
|
||||
{
|
||||
let mut new_build_obj: Option<String> = None;
|
||||
if let Ok(obj_path) = path.strip_prefix(&build_src_dir) {
|
||||
new_build_obj = Some(obj_path.display().to_string());
|
||||
} else if let Some(build_asm_dir) = build_asm_dir {
|
||||
if let Ok(obj_path) = path.strip_prefix(&build_asm_dir) {
|
||||
new_build_obj = Some(obj_path.display().to_string());
|
||||
}
|
||||
}
|
||||
if let Some(new_build_obj) = new_build_obj {
|
||||
*build_obj = Some(new_build_obj.clone());
|
||||
view_state.jobs.push(queue_build(new_build_obj, config.clone()));
|
||||
}
|
||||
}
|
||||
if let Some(new_build_obj) = new_build_obj {
|
||||
*build_obj = Some(new_build_obj.clone());
|
||||
view_state.jobs.push(queue_build(new_build_obj, config.clone()));
|
||||
}
|
||||
if let Some(build_obj) = build_obj {
|
||||
ui.label(&*build_obj);
|
||||
if ui.button("Build").clicked() {
|
||||
view_state.jobs.push(queue_build(build_obj.clone(), config.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
ui.separator();
|
||||
}
|
||||
if let Some(build_obj) = build_obj {
|
||||
ui.label(&*build_obj);
|
||||
if ui.button("Build").clicked() {
|
||||
view_state.jobs.push(queue_build(build_obj.clone(), config.clone()));
|
||||
} else if view_state.diff_kind == DiffKind::WholeBinary {
|
||||
if ui.button("Select left obj").clicked() {
|
||||
if let Some(path) =
|
||||
rfd::FileDialog::new().add_filter("Object file", &["o", "elf"]).pick_file()
|
||||
{
|
||||
*left_obj = Some(path);
|
||||
}
|
||||
}
|
||||
if let Some(obj) = left_obj {
|
||||
ui.label(obj.to_string_lossy());
|
||||
}
|
||||
|
||||
ui.separator();
|
||||
if ui.button("Select right obj").clicked() {
|
||||
if let Some(path) =
|
||||
rfd::FileDialog::new().add_filter("Object file", &["o", "elf"]).pick_file()
|
||||
{
|
||||
*right_obj = Some(path);
|
||||
}
|
||||
}
|
||||
if let Some(obj) = right_obj {
|
||||
ui.label(obj.to_string_lossy());
|
||||
}
|
||||
|
||||
if let (Some(_), Some(_)) = (left_obj, right_obj) {
|
||||
if ui.button("Build").clicked() {
|
||||
view_state.jobs.push(queue_bindiff(config.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui.checkbox(&mut view_state.reverse_fn_order, "Reverse function order (deferred)");
|
||||
|
||||
@@ -25,13 +25,39 @@ fn write_text(str: &str, color: Color32, job: &mut LayoutJob) {
|
||||
|
||||
fn write_reloc(reloc: &ObjReloc, job: &mut LayoutJob) {
|
||||
let name = reloc.target.demangled_name.as_ref().unwrap_or(&reloc.target.name);
|
||||
write_text(name, Color32::LIGHT_GRAY, job);
|
||||
match reloc.kind {
|
||||
ObjRelocKind::PpcAddr16Lo => write_text("@l", Color32::GRAY, job),
|
||||
ObjRelocKind::PpcAddr16Hi => write_text("@h", Color32::GRAY, job),
|
||||
ObjRelocKind::PpcAddr16Ha => write_text("@ha", Color32::GRAY, job),
|
||||
ObjRelocKind::PpcEmbSda21 => write_text("@sda21", Color32::GRAY, job),
|
||||
_ => {}
|
||||
ObjRelocKind::PpcAddr16Lo => {
|
||||
write_text(name, Color32::LIGHT_GRAY, job);
|
||||
write_text("@l", Color32::GRAY, job);
|
||||
}
|
||||
ObjRelocKind::PpcAddr16Hi => {
|
||||
write_text(name, Color32::LIGHT_GRAY, job);
|
||||
write_text("@h", Color32::GRAY, job);
|
||||
}
|
||||
ObjRelocKind::PpcAddr16Ha => {
|
||||
write_text(name, Color32::LIGHT_GRAY, job);
|
||||
write_text("@ha", Color32::GRAY, job);
|
||||
}
|
||||
ObjRelocKind::PpcEmbSda21 => {
|
||||
write_text(name, Color32::LIGHT_GRAY, job);
|
||||
write_text("@sda21", Color32::GRAY, job);
|
||||
}
|
||||
ObjRelocKind::MipsHi16 => {
|
||||
write_text("%hi(", Color32::GRAY, job);
|
||||
write_text(name, Color32::LIGHT_GRAY, job);
|
||||
write_text(")", Color32::GRAY, job);
|
||||
}
|
||||
ObjRelocKind::MipsLo16 => {
|
||||
write_text("%lo(", Color32::GRAY, job);
|
||||
write_text(name, Color32::LIGHT_GRAY, job);
|
||||
write_text(")", Color32::GRAY, job);
|
||||
}
|
||||
ObjRelocKind::Absolute
|
||||
| ObjRelocKind::PpcRel24
|
||||
| ObjRelocKind::PpcRel14
|
||||
| ObjRelocKind::Mips26 => {
|
||||
write_text(name, Color32::LIGHT_GRAY, job);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -51,7 +77,7 @@ fn write_ins(
|
||||
ObjInsDiffKind::Insert => Color32::GREEN,
|
||||
};
|
||||
write_text(
|
||||
&ins.mnemonic,
|
||||
&format!("{:<11}", ins.mnemonic),
|
||||
match diff_kind {
|
||||
ObjInsDiffKind::OpMismatch => Color32::LIGHT_BLUE,
|
||||
_ => base_color,
|
||||
@@ -72,17 +98,13 @@ fn write_ins(
|
||||
base_color
|
||||
};
|
||||
match arg {
|
||||
ObjInsArg::Arg(arg) => match arg {
|
||||
ObjInsArg::PpcArg(arg) => match arg {
|
||||
Argument::Offset(val) => {
|
||||
write_text(&format!("{}", val), color, job);
|
||||
write_text("(", base_color, job);
|
||||
writing_offset = true;
|
||||
continue;
|
||||
}
|
||||
Argument::BranchDest(dest) => {
|
||||
let addr = dest.0 + ins.ins.addr as i32 - base_addr as i32;
|
||||
write_text(&format!("{:x}", addr), color, job);
|
||||
}
|
||||
Argument::Uimm(_) | Argument::Simm(_) => {
|
||||
write_text(&format!("{}", arg), color, job);
|
||||
}
|
||||
@@ -93,12 +115,19 @@ fn write_ins(
|
||||
ObjInsArg::Reloc => {
|
||||
write_reloc(ins.reloc.as_ref().unwrap(), job);
|
||||
}
|
||||
ObjInsArg::RelocOffset => {
|
||||
ObjInsArg::RelocWithBase => {
|
||||
write_reloc(ins.reloc.as_ref().unwrap(), job);
|
||||
write_text("(", base_color, job);
|
||||
writing_offset = true;
|
||||
continue;
|
||||
}
|
||||
ObjInsArg::MipsArg(str) => {
|
||||
write_text(str.strip_prefix('$').unwrap_or(str), color, job);
|
||||
}
|
||||
ObjInsArg::BranchOffset(offset) => {
|
||||
let addr = offset + ins.address as i32 - base_addr as i32;
|
||||
write_text(&format!("{:x}", addr), color, job);
|
||||
}
|
||||
}
|
||||
if writing_offset {
|
||||
write_text(")", base_color, job);
|
||||
@@ -112,10 +141,10 @@ fn ins_hover_ui(ui: &mut egui::Ui, ins: &ObjIns) {
|
||||
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
|
||||
ui.style_mut().wrap = Some(false);
|
||||
|
||||
ui.label(format!("{:02X?}", ins.ins.code.to_be_bytes()));
|
||||
ui.label(format!("{:02X?}", ins.code.to_be_bytes()));
|
||||
|
||||
for arg in &ins.args {
|
||||
if let ObjInsArg::Arg(arg) = arg {
|
||||
if let ObjInsArg::PpcArg(arg) = arg {
|
||||
match arg {
|
||||
Argument::Uimm(v) => {
|
||||
ui.label(format!("{} == {}", v, v.0));
|
||||
@@ -153,7 +182,7 @@ fn ins_context_menu(ui: &mut egui::Ui, ins: &ObjIns) {
|
||||
// if ui.button("Copy hex").clicked() {}
|
||||
|
||||
for arg in &ins.args {
|
||||
if let ObjInsArg::Arg(arg) = arg {
|
||||
if let ObjInsArg::PpcArg(arg) = arg {
|
||||
match arg {
|
||||
Argument::Uimm(v) => {
|
||||
if ui.button(format!("Copy \"{}\"", v)).clicked() {
|
||||
@@ -236,7 +265,7 @@ fn asm_row_ui(ui: &mut egui::Ui, ins_diff: &ObjInsDiff, symbol: &ObjSymbol) {
|
||||
ObjInsDiffKind::Insert => Color32::GREEN,
|
||||
};
|
||||
write_text(
|
||||
&format!("{:<6}", format!("{:x}:", ins.ins.addr - symbol.address as u32)),
|
||||
&format!("{:<6}", format!("{:x}:", ins.address - symbol.address as u32)),
|
||||
base_color,
|
||||
&mut job,
|
||||
);
|
||||
|
||||
@@ -66,21 +66,28 @@ fn symbol_ui(
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
job.append("] (", 0.0, TextFormat {
|
||||
font_id: font_id.clone(),
|
||||
color: Color32::GRAY,
|
||||
..Default::default()
|
||||
});
|
||||
job.append(&format!("{:.0}%", symbol.match_percent), 0.0, TextFormat {
|
||||
font_id: font_id.clone(),
|
||||
color: match_color_for_symbol(symbol),
|
||||
..Default::default()
|
||||
});
|
||||
job.append(") ", 0.0, TextFormat {
|
||||
job.append("] ", 0.0, TextFormat {
|
||||
font_id: font_id.clone(),
|
||||
color: Color32::GRAY,
|
||||
..Default::default()
|
||||
});
|
||||
if symbol.match_percent > 0.0 {
|
||||
job.append("(", 0.0, TextFormat {
|
||||
font_id: font_id.clone(),
|
||||
color: Color32::GRAY,
|
||||
..Default::default()
|
||||
});
|
||||
job.append(&format!("{:.0}%", symbol.match_percent), 0.0, TextFormat {
|
||||
font_id: font_id.clone(),
|
||||
color: match_color_for_symbol(symbol),
|
||||
..Default::default()
|
||||
});
|
||||
job.append(") ", 0.0, TextFormat {
|
||||
font_id: font_id.clone(),
|
||||
color: Color32::GRAY,
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
job.append(name, 0.0, TextFormat { font_id, color: Color32::WHITE, ..Default::default() });
|
||||
let response = SelectableLabel::new(selected, job).ui(ui);
|
||||
if response.clicked() {
|
||||
|
||||
Reference in New Issue
Block a user