Skip to content

Commit 95868f1

Browse files
committed
Reimplement x86 arch, MSVC section group combining
Plus display_row/DiffText refactoring
1 parent 506c251 commit 95868f1

29 files changed

+2570
-1034
lines changed

.github/workflows/build.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,6 @@ jobs:
235235
- name: Setup Rust toolchain
236236
uses: dtolnay/rust-toolchain@nightly
237237
with:
238-
targets: wasm32-wasip2
239238
components: rust-src
240239
- name: Cache Rust workspace
241240
uses: Swatinem/rust-cache@v2

objdiff-cli/src/views/function_diff.rs

Lines changed: 35 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use std::cmp::Ordering;
1+
use core::cmp::Ordering;
22

33
use anyhow::{bail, Result};
44
use crossterm::event::{Event, KeyCode, KeyEventKind, KeyModifiers, MouseButton, MouseEventKind};
55
use objdiff_core::{
66
diff::{
7-
display::{display_row, DiffText, HighlightKind},
7+
display::{display_row, DiffText, DiffTextColor, HighlightKind},
88
DiffObjConfig, FunctionRelocDiffs, InstructionDiffKind, ObjectDiff, SymbolDiff,
99
},
1010
obj::Object,
@@ -522,87 +522,55 @@ impl FunctionDiffUi {
522522
let mut sx = rect.x;
523523
let sy = rect.y + y as u16;
524524
let mut line = Line::default();
525-
display_row(obj, symbol_index, ins_row, diff_config, |text, diff_idx| {
526-
let label_text;
527-
let mut base_color = match ins_row.kind {
528-
InstructionDiffKind::None
529-
| InstructionDiffKind::OpMismatch
530-
| InstructionDiffKind::ArgMismatch => Color::Gray,
531-
InstructionDiffKind::Replace => Color::Cyan,
532-
InstructionDiffKind::Delete => Color::Red,
533-
InstructionDiffKind::Insert => Color::Green,
534-
};
535-
if let Some(idx) = diff_idx.get() {
536-
base_color = COLOR_ROTATION[idx as usize % COLOR_ROTATION.len()];
537-
}
538-
let mut pad_to = 0;
539-
match text {
540-
DiffText::Basic(text) => {
541-
label_text = text.to_string();
542-
}
543-
DiffText::Line(num) => {
544-
label_text = format!("{num} ");
545-
base_color = Color::DarkGray;
546-
pad_to = 5;
547-
}
548-
DiffText::Address(addr) => {
549-
label_text = format!("{:x}:", addr);
550-
pad_to = 5;
551-
}
552-
DiffText::Opcode(mnemonic, _op) => {
553-
label_text = mnemonic.to_string();
554-
if ins_row.kind == InstructionDiffKind::OpMismatch {
555-
base_color = Color::Blue;
556-
}
557-
pad_to = 8;
558-
}
559-
DiffText::Argument(arg) => {
560-
label_text = arg.to_string();
561-
}
562-
DiffText::BranchDest(addr) => {
563-
label_text = format!("{addr:x}");
564-
}
525+
display_row(obj, symbol_index, ins_row, diff_config, |segment| {
526+
let highlight_kind = HighlightKind::from(&segment.text);
527+
let label_text = match segment.text {
528+
DiffText::Basic(text) => text.to_string(),
529+
DiffText::Line(num) => format!("{num} "),
530+
DiffText::Address(addr) => format!("{:x}:", addr),
531+
DiffText::Opcode(mnemonic, _op) => format!("{mnemonic} "),
532+
DiffText::Argument(arg) => arg.to_string(),
533+
DiffText::BranchDest(addr) => format!("{addr:x}"),
565534
DiffText::Symbol(sym) => {
566-
let name = sym.demangled_name.as_ref().unwrap_or(&sym.name);
567-
label_text = name.clone();
568-
if diff_idx.is_none() {
569-
base_color = Color::White;
570-
}
571-
}
572-
DiffText::Addend(addend) => {
573-
label_text = match addend.cmp(&0i64) {
574-
Ordering::Greater => format!("+{:#x}", addend),
575-
Ordering::Less => format!("-{:#x}", -addend),
576-
_ => "".to_string(),
577-
};
578-
if diff_idx.is_none() {
579-
base_color = Color::White;
580-
}
535+
sym.demangled_name.as_ref().unwrap_or(&sym.name).clone()
581536
}
537+
DiffText::Addend(addend) => match addend.cmp(&0i64) {
538+
Ordering::Greater => format!("+{:#x}", addend),
539+
Ordering::Less => format!("-{:#x}", -addend),
540+
_ => String::new(),
541+
},
582542
DiffText::Spacing(n) => {
583-
line.spans.push(Span::raw(" ".repeat(n)));
543+
line.spans.push(Span::raw(" ".repeat(n as usize)));
584544
sx += n as u16;
585545
return Ok(());
586546
}
587-
DiffText::Eol => {
588-
return Ok(());
589-
}
590-
}
547+
DiffText::Eol => return Ok(()),
548+
};
549+
591550
let len = label_text.len();
592-
let highlighted = *highlight == text;
551+
let highlighted =
552+
highlight_kind != HighlightKind::None && *highlight == highlight_kind;
593553
if let Some((cx, cy)) = result.click_xy {
594554
if cx >= sx && cx < sx + len as u16 && cy == sy {
595-
new_highlight = Some(text.into());
555+
new_highlight = Some(highlight_kind);
596556
}
597557
}
598-
let mut style = Style::new().fg(base_color);
558+
let mut style = Style::new().fg(match segment.color {
559+
DiffTextColor::Normal => Color::Gray,
560+
DiffTextColor::Dim => Color::DarkGray,
561+
DiffTextColor::Bright => Color::White,
562+
DiffTextColor::Replace => Color::Cyan,
563+
DiffTextColor::Delete => Color::Red,
564+
DiffTextColor::Insert => Color::Green,
565+
DiffTextColor::Rotating(i) => COLOR_ROTATION[i as usize % COLOR_ROTATION.len()],
566+
});
599567
if highlighted {
600568
style = style.bg(Color::DarkGray);
601569
}
602570
line.spans.push(Span::styled(label_text, style));
603571
sx += len as u16;
604-
if pad_to > len {
605-
let pad = (pad_to - len) as u16;
572+
if segment.pad_to as usize > len {
573+
let pad = (segment.pad_to as usize - len) as u16;
606574
line.spans.push(Span::raw(" ".repeat(pad as usize)));
607575
sx += pad;
608576
}

objdiff-core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ all = [
2626
"arm64",
2727
"mips",
2828
"ppc",
29-
# "x86",
29+
"x86",
3030
]
3131
# Implicit, used to check if any arch is enabled
3232
any-arch = [

objdiff-core/src/arch/arm.rs

Lines changed: 51 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ use crate::{
1616
arch::Arch,
1717
diff::{display::InstructionPart, ArmArchVersion, ArmR9Usage, DiffObjConfig},
1818
obj::{
19-
InstructionArg, InstructionArgValue, InstructionRef, RelocationFlags, ResolvedRelocation,
20-
ScannedInstruction, SymbolFlag, SymbolFlagSet, SymbolKind,
19+
InstructionRef, RelocationFlags, ResolvedRelocation, ScannedInstruction, SymbolFlag,
20+
SymbolFlagSet, SymbolKind,
2121
},
2222
};
2323

@@ -261,9 +261,9 @@ impl Arch for ArchArm {
261261
cb: &mut dyn FnMut(InstructionPart) -> Result<()>,
262262
) -> Result<()> {
263263
let (ins, parsed_ins) = self.parse_ins_ref(ins_ref, code, diff_config)?;
264-
cb(InstructionPart::Opcode(Cow::Borrowed(parsed_ins.mnemonic), ins_ref.opcode))?;
264+
cb(InstructionPart::opcode(parsed_ins.mnemonic, ins_ref.opcode))?;
265265
if ins == unarm::Ins::Data && relocation.is_some() {
266-
cb(InstructionPart::Arg(InstructionArg::Reloc))?;
266+
cb(InstructionPart::reloc())?;
267267
} else {
268268
push_args(
269269
&parsed_ins,
@@ -396,143 +396,109 @@ fn push_args(
396396
})
397397
| args::Argument::CoOption(_) => {
398398
deref = false;
399-
arg_cb(InstructionPart::Basic("]"))?;
399+
arg_cb(InstructionPart::basic("]"))?;
400400
if writeback {
401401
writeback = false;
402-
arg_cb(InstructionPart::Arg(InstructionArg::Value(
403-
InstructionArgValue::Opaque("!".into()),
404-
)))?;
402+
arg_cb(InstructionPart::opaque("!"))?;
405403
}
406404
}
407405
_ => {}
408406
}
409407
}
410408

411409
if i > 0 {
412-
arg_cb(InstructionPart::Separator)?;
410+
arg_cb(InstructionPart::separator())?;
413411
}
414412

415413
if reloc_arg == Some(i) {
416-
arg_cb(InstructionPart::Arg(InstructionArg::Reloc))?;
414+
arg_cb(InstructionPart::reloc())?;
417415
} else {
418416
match arg {
419417
args::Argument::None => {}
420418
args::Argument::Reg(reg) => {
421419
if reg.deref {
422420
deref = true;
423-
arg_cb(InstructionPart::Basic("["))?;
421+
arg_cb(InstructionPart::basic("["))?;
424422
}
425-
arg_cb(InstructionPart::Arg(InstructionArg::Value(
426-
InstructionArgValue::Opaque(
427-
reg.reg.display(display_options.reg_names).to_string().into(),
428-
),
429-
)))?;
423+
arg_cb(InstructionPart::opaque(
424+
reg.reg.display(display_options.reg_names).to_string(),
425+
))?;
430426
if reg.writeback {
431427
if reg.deref {
432428
writeback = true;
433429
} else {
434-
arg_cb(InstructionPart::Arg(InstructionArg::Value(
435-
InstructionArgValue::Opaque("!".into()),
436-
)))?;
430+
arg_cb(InstructionPart::opaque("!"))?;
437431
}
438432
}
439433
}
440434
args::Argument::RegList(reg_list) => {
441-
arg_cb(InstructionPart::Basic("{"))?;
435+
arg_cb(InstructionPart::basic("{"))?;
442436
let mut first = true;
443437
for i in 0..16 {
444438
if (reg_list.regs & (1 << i)) != 0 {
445439
if !first {
446-
arg_cb(InstructionPart::Separator)?;
440+
arg_cb(InstructionPart::separator())?;
447441
}
448-
arg_cb(InstructionPart::Arg(InstructionArg::Value(
449-
InstructionArgValue::Opaque(
450-
args::Register::parse(i)
451-
.display(display_options.reg_names)
452-
.to_string()
453-
.into(),
454-
),
455-
)))?;
442+
arg_cb(InstructionPart::opaque(
443+
args::Register::parse(i)
444+
.display(display_options.reg_names)
445+
.to_string(),
446+
))?;
456447
first = false;
457448
}
458449
}
459-
arg_cb(InstructionPart::Basic("}"))?;
450+
arg_cb(InstructionPart::basic("}"))?;
460451
if reg_list.user_mode {
461-
arg_cb(InstructionPart::Arg(InstructionArg::Value(
462-
InstructionArgValue::Opaque("^".into()),
463-
)))?;
452+
arg_cb(InstructionPart::opaque("^"))?;
464453
}
465454
}
466455
args::Argument::UImm(value)
467456
| args::Argument::CoOpcode(value)
468457
| args::Argument::SatImm(value) => {
469-
arg_cb(InstructionPart::Basic("#"))?;
470-
arg_cb(InstructionPart::Arg(InstructionArg::Value(
471-
InstructionArgValue::Unsigned(*value as u64),
472-
)))?;
458+
arg_cb(InstructionPart::basic("#"))?;
459+
arg_cb(InstructionPart::unsigned(*value))?;
473460
}
474461
args::Argument::SImm(value)
475462
| args::Argument::OffsetImm(args::OffsetImm { post_indexed: _, value }) => {
476-
arg_cb(InstructionPart::Basic("#"))?;
477-
arg_cb(InstructionPart::Arg(InstructionArg::Value(
478-
InstructionArgValue::Signed(*value as i64),
479-
)))?;
463+
arg_cb(InstructionPart::basic("#"))?;
464+
arg_cb(InstructionPart::signed(*value))?;
480465
}
481466
args::Argument::BranchDest(value) => {
482-
let dest = cur_addr.wrapping_add_signed(*value) as u64;
483-
arg_cb(InstructionPart::Arg(InstructionArg::BranchDest(dest)))?;
467+
arg_cb(InstructionPart::branch_dest(cur_addr.wrapping_add_signed(*value)))?;
484468
}
485469
args::Argument::CoOption(value) => {
486-
arg_cb(InstructionPart::Basic("{"))?;
487-
arg_cb(InstructionPart::Arg(InstructionArg::Value(
488-
InstructionArgValue::Unsigned(*value as u64),
489-
)))?;
490-
arg_cb(InstructionPart::Basic("}"))?;
470+
arg_cb(InstructionPart::basic("{"))?;
471+
arg_cb(InstructionPart::unsigned(*value))?;
472+
arg_cb(InstructionPart::basic("}"))?;
491473
}
492474
args::Argument::CoprocNum(value) => {
493-
arg_cb(InstructionPart::Arg(InstructionArg::Value(
494-
InstructionArgValue::Opaque(format!("p{}", value).into()),
495-
)))?;
475+
arg_cb(InstructionPart::opaque(format!("p{}", value)))?;
496476
}
497477
args::Argument::ShiftImm(shift) => {
498-
arg_cb(InstructionPart::Arg(InstructionArg::Value(
499-
InstructionArgValue::Opaque(shift.op.to_string().into()),
500-
)))?;
501-
arg_cb(InstructionPart::Basic(" #"))?;
502-
arg_cb(InstructionPart::Arg(InstructionArg::Value(
503-
InstructionArgValue::Unsigned(shift.imm as u64),
504-
)))?;
478+
arg_cb(InstructionPart::opaque(shift.op.to_string()))?;
479+
arg_cb(InstructionPart::basic(" #"))?;
480+
arg_cb(InstructionPart::unsigned(shift.imm))?;
505481
}
506482
args::Argument::ShiftReg(shift) => {
507-
arg_cb(InstructionPart::Arg(InstructionArg::Value(
508-
InstructionArgValue::Opaque(shift.op.to_string().into()),
509-
)))?;
510-
arg_cb(InstructionPart::Basic(" "))?;
511-
arg_cb(InstructionPart::Arg(InstructionArg::Value(
512-
InstructionArgValue::Opaque(
513-
shift.reg.display(display_options.reg_names).to_string().into(),
514-
),
515-
)))?;
483+
arg_cb(InstructionPart::opaque(shift.op.to_string()))?;
484+
arg_cb(InstructionPart::basic(" "))?;
485+
arg_cb(InstructionPart::opaque(
486+
shift.reg.display(display_options.reg_names).to_string(),
487+
))?;
516488
}
517489
args::Argument::OffsetReg(offset) => {
518490
if !offset.add {
519-
arg_cb(InstructionPart::Basic("-"))?;
491+
arg_cb(InstructionPart::basic("-"))?;
520492
}
521-
arg_cb(InstructionPart::Arg(InstructionArg::Value(
522-
InstructionArgValue::Opaque(
523-
offset.reg.display(display_options.reg_names).to_string().into(),
524-
),
525-
)))?;
493+
arg_cb(InstructionPart::opaque(
494+
offset.reg.display(display_options.reg_names).to_string(),
495+
))?;
526496
}
527497
args::Argument::CpsrMode(mode) => {
528-
arg_cb(InstructionPart::Basic("#"))?;
529-
arg_cb(InstructionPart::Arg(InstructionArg::Value(
530-
InstructionArgValue::Unsigned(mode.mode as u64),
531-
)))?;
498+
arg_cb(InstructionPart::basic("#"))?;
499+
arg_cb(InstructionPart::unsigned(mode.mode))?;
532500
if mode.writeback {
533-
arg_cb(InstructionPart::Arg(InstructionArg::Value(
534-
InstructionArgValue::Opaque("!".into()),
535-
)))?;
501+
arg_cb(InstructionPart::opaque("!"))?;
536502
}
537503
}
538504
args::Argument::CoReg(_)
@@ -541,21 +507,17 @@ fn push_args(
541507
| args::Argument::Shift(_)
542508
| args::Argument::CpsrFlags(_)
543509
| args::Argument::Endian(_) => {
544-
arg_cb(InstructionPart::Arg(InstructionArg::Value(
545-
InstructionArgValue::Opaque(
546-
arg.display(display_options, None).to_string().into(),
547-
),
548-
)))?;
510+
arg_cb(InstructionPart::opaque(
511+
arg.display(display_options, None).to_string(),
512+
))?;
549513
}
550514
}
551515
}
552516
}
553517
if deref {
554-
arg_cb(InstructionPart::Basic("]"))?;
518+
arg_cb(InstructionPart::basic("]"))?;
555519
if writeback {
556-
arg_cb(InstructionPart::Arg(InstructionArg::Value(InstructionArgValue::Opaque(
557-
"!".into(),
558-
))))?;
520+
arg_cb(InstructionPart::opaque("!"))?;
559521
}
560522
}
561523
Ok(())

0 commit comments

Comments
 (0)