@@ -23,7 +23,7 @@ use crate::{
2323 column_layout:: { render_header, render_strips, render_table} ,
2424 data_diff:: data_row_ui,
2525 extab_diff:: extab_ui,
26- function_diff:: { FunctionDiffContext , asm_col_ui} ,
26+ function_diff:: { FunctionDiffContext , GoToTarget , GoToTargetType , asm_col_ui} ,
2727 symbol_diff:: {
2828 DiffViewAction , DiffViewNavigation , DiffViewState , SymbolDiffContext , SymbolRefByName ,
2929 View , match_color_for_symbol, symbol_context_menu_ui, symbol_hover_ui, symbol_list_ui,
@@ -116,25 +116,54 @@ fn get_asm_text(
116116 asm_text
117117}
118118
119- fn try_scroll_to_line_number (
120- scroll_to_line_number : Option < u32 > ,
119+ fn try_scroll_to_go_to_target (
120+ go_to_target : GoToTarget ,
121121 obj : & Object ,
122122 diff : & ObjectDiff ,
123123 symbol_idx : usize ,
124124) -> Option < DiffViewAction > {
125- let target_line = scroll_to_line_number?;
126- let symbol = obj. symbols . get ( symbol_idx) ?;
127- let section_index = symbol. section ?;
128- let section = & obj. sections [ section_index] ;
129- for ( ins_idx, ins_row) in diff. symbols [ symbol_idx] . instruction_rows . iter ( ) . enumerate ( ) {
130- if let Some ( ins_ref) = ins_row. ins_ref
131- && let Some ( current_line) =
132- section. line_info . range ( ..=ins_ref. address ) . last ( ) . map ( |( _, & b) | b)
133- && current_line == target_line
134- {
135- return Some ( DiffViewAction :: ScrollToRow ( ins_idx) ) ;
125+ match go_to_target {
126+ GoToTarget :: None => return None ,
127+ GoToTarget :: LineNumber ( target_line) => {
128+ let symbol = obj. symbols . get ( symbol_idx) ?;
129+ let section_index = symbol. section ?;
130+ let section = & obj. sections [ section_index] ;
131+ for ( ins_idx, ins_row) in diff. symbols [ symbol_idx] . instruction_rows . iter ( ) . enumerate ( ) {
132+ if let Some ( ins_ref) = ins_row. ins_ref
133+ && let Some ( current_line) =
134+ section. line_info . range ( ..=ins_ref. address ) . last ( ) . map ( |( _, & b) | b)
135+ && current_line == target_line
136+ {
137+ return Some ( DiffViewAction :: ScrollToRow ( ins_idx) ) ;
138+ }
139+ }
136140 }
137- }
141+ GoToTarget :: Address ( target_address) => {
142+ let symbol = obj. symbols . get ( symbol_idx) ?;
143+ let symbol_diff = diff. symbols . get ( symbol_idx) ?;
144+ for ( ins_idx, ins_row) in symbol_diff. instruction_rows . iter ( ) . enumerate ( ) {
145+ if let Some ( ins_ref) = ins_row. ins_ref
146+ && target_address == ins_ref. address . saturating_sub ( symbol. address )
147+ {
148+ return Some ( DiffViewAction :: ScrollToRow ( ins_idx) ) ;
149+ }
150+ }
151+ }
152+ GoToTarget :: VirtualAddress ( target_virtual_address) => {
153+ let symbol = obj. symbols . get ( symbol_idx) ?;
154+ let section_index = symbol. section ?;
155+ let section = & obj. sections [ section_index] ;
156+ let section_virtual_address = section. virtual_address ?;
157+ let target_offset = target_virtual_address. checked_sub ( section_virtual_address) ?;
158+ for ( ins_idx, ins_row) in diff. symbols [ symbol_idx] . instruction_rows . iter ( ) . enumerate ( ) {
159+ if let Some ( ins_ref) = ins_row. ins_ref
160+ && ins_ref. address == target_offset
161+ {
162+ return Some ( DiffViewAction :: ScrollToRow ( ins_idx) ) ;
163+ }
164+ }
165+ }
166+ } ;
138167 None
139168}
140169
@@ -309,6 +338,44 @@ pub fn diff_view_ui(
309338 {
310339 ret = Some ( DiffViewAction :: SelectingLeft ( symbol_ref. clone ( ) ) ) ;
311340 }
341+
342+ if state. current_view == View :: FunctionDiff {
343+ ui. separator ( ) ;
344+
345+ let mut goto_line_text = state. function_state . go_to_text_left . clone ( ) ;
346+ let response = TextEdit :: singleline ( & mut goto_line_text)
347+ . hint_text ( "Go to..." )
348+ . desired_width ( 100.0 )
349+ . ui ( ui) ;
350+
351+ let mut go_to_target_type_left: GoToTargetType =
352+ state. function_state . go_to_target_type_left ;
353+ egui:: ComboBox :: from_id_salt ( "go_to_target_type_left" )
354+ . selected_text ( go_to_target_type_left. to_string ( ) )
355+ . show_ui ( ui, |ui| {
356+ for go_to_target_type in [
357+ GoToTargetType :: LineNumber ,
358+ GoToTargetType :: Address ,
359+ GoToTargetType :: VirtualAddress ,
360+ ] {
361+ let response = ui. selectable_value (
362+ & mut go_to_target_type_left,
363+ go_to_target_type,
364+ go_to_target_type. to_string ( ) ,
365+ ) ;
366+ if response. changed ( ) {
367+ ret = Some ( DiffViewAction :: SetGoToTargetType (
368+ go_to_target_type_left,
369+ false ,
370+ ) ) ;
371+ }
372+ }
373+ } ) ;
374+
375+ if response. changed ( ) {
376+ ret = Some ( DiffViewAction :: SetGoToText ( goto_line_text, false ) ) ;
377+ }
378+ }
312379 } ) ;
313380 } else if left_ctx. status . success && !left_ctx. has_symbol ( ) {
314381 ui. horizontal ( |ui| {
@@ -480,22 +547,53 @@ pub fn diff_view_ui(
480547 needs_separator = true ;
481548 }
482549
483- if state. current_view == View :: FunctionDiff
484- || state. current_view == View :: DataDiff
485- {
550+ if state. current_view == View :: FunctionDiff {
486551 if needs_separator {
487552 ui. separator ( ) ;
488553 }
489- let mut goto_line_text = state. function_state . go_to_line_text . clone ( ) ;
554+ let mut goto_line_text = state. function_state . go_to_text_right . clone ( ) ;
490555 let response = TextEdit :: singleline ( & mut goto_line_text)
491- . hint_text ( "Go to line number " )
556+ . hint_text ( "Go to... " )
492557 . desired_width ( 100.0 )
493558 . ui ( ui) ;
494559 if hotkeys:: consume_go_to_shortcut ( ui. ctx ( ) ) {
495560 response. request_focus ( ) ;
496561 }
562+
563+ let mut go_to_target_type_right: GoToTargetType =
564+ state. function_state . go_to_target_type_right ;
565+ egui:: ComboBox :: from_id_salt ( "go_to_target_type_right" )
566+ . selected_text ( go_to_target_type_right. to_string ( ) )
567+ . show_ui ( ui, |ui| {
568+ for go_to_target_type in [
569+ GoToTargetType :: LineNumber ,
570+ GoToTargetType :: Address ,
571+ GoToTargetType :: VirtualAddress ,
572+ ] {
573+ let response = ui. selectable_value (
574+ & mut go_to_target_type_right,
575+ go_to_target_type,
576+ go_to_target_type. to_string ( ) ,
577+ ) ;
578+ if response. changed ( ) {
579+ ret = Some ( DiffViewAction :: SetGoToTargetType (
580+ go_to_target_type_right,
581+ true ,
582+ ) ) ;
583+ }
584+ }
585+ } ) ;
586+
497587 if response. changed ( ) {
498- ret = Some ( DiffViewAction :: SetGoToText ( goto_line_text) ) ;
588+ ret = Some ( DiffViewAction :: SetGoToText ( goto_line_text, true ) ) ;
589+ }
590+ }
591+
592+ if state. current_view == View :: FunctionDiff
593+ || state. current_view == View :: DataDiff
594+ {
595+ if needs_separator {
596+ ui. separator ( ) ;
499597 }
500598 if ui
501599 . button ( "⏴ Prev diff" )
@@ -555,11 +653,15 @@ pub fn diff_view_ui(
555653 ui. label ( "Instruction count mismatch" ) ;
556654 return ;
557655 }
558- if let Some ( action) = try_scroll_to_line_number (
559- state. function_state . scroll_to_line_number ,
560- right_obj,
561- right_diff,
562- right_symbol_idx,
656+ if let Some ( action) = try_scroll_to_go_to_target (
657+ state. function_state . go_to_target ,
658+ if state. function_state . go_to_target_is_right { right_obj } else { left_obj } ,
659+ if state. function_state . go_to_target_is_right { right_diff } else { left_diff } ,
660+ if state. function_state . go_to_target_is_right {
661+ right_symbol_idx
662+ } else {
663+ left_symbol_idx
664+ } ,
563665 ) {
564666 ret = Some ( action) ;
565667 }
@@ -840,8 +942,8 @@ fn diff_col_ui(
840942 } ,
841943 ) ;
842944 } else {
843- if let Some ( action) = try_scroll_to_line_number (
844- state. function_state . scroll_to_line_number ,
945+ if let Some ( action) = try_scroll_to_go_to_target (
946+ state. function_state . go_to_target ,
845947 obj,
846948 diff,
847949 symbol_idx,
0 commit comments