test mi
This commit is contained in:
parent
8180c3cf13
commit
40f40ed3f7
File diff suppressed because it is too large
Load Diff
@ -34,18 +34,7 @@ class SymbolAnalyzer:
|
||||
target_exe_path: str,
|
||||
progress_callback: Optional[Callable[[str], None]] = None,
|
||||
status_callback: Optional[Callable[[str], None]] = None) -> Dict[str, Any]:
|
||||
"""
|
||||
Performs a full symbol analysis of the target executable using GDB.
|
||||
|
||||
Args:
|
||||
target_exe_path: The full path to the target executable.
|
||||
progress_callback: A callback function (str) -> None to log detailed progress.
|
||||
status_callback: A callback function (str) -> None to update general status.
|
||||
|
||||
Returns:
|
||||
A dictionary containing all analyzed symbol data, or an empty dict on critical failure.
|
||||
"""
|
||||
# Inizializza la struttura dati completa per l'analisi
|
||||
analysis_data_dict: Dict[str, Any] = {
|
||||
"analyzed_executable_path": target_exe_path,
|
||||
"executable_checksum": None,
|
||||
@ -55,12 +44,12 @@ class SymbolAnalyzer:
|
||||
"symbols": {
|
||||
"functions": [],
|
||||
"functions_count": 0,
|
||||
"global_variables": [], # Per Iterazione 3
|
||||
"global_variables_count": 0,# Per Iterazione 3
|
||||
"types": [], # Per Iterazione 3
|
||||
"types_count": 0, # Per Iterazione 3
|
||||
"source_files": [], # Per Iterazione 3
|
||||
"source_files_count": 0 # Per Iterazione 3
|
||||
"global_variables": [],
|
||||
"global_variables_count": 0,
|
||||
"types": [],
|
||||
"types_count": 0,
|
||||
"source_files": [], # Placeholder per futura iterazione
|
||||
"source_files_count": 0 # Placeholder per futura iterazione
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,8 +68,9 @@ class SymbolAnalyzer:
|
||||
self._temp_gdb_session = GDBSession(
|
||||
gdb_path=self.gdb_exe_path,
|
||||
executable_path=target_exe_path,
|
||||
gdb_script_full_path=None, # Non serve lo script dumper per l'analisi
|
||||
dumper_options={}
|
||||
gdb_script_full_path=None,
|
||||
dumper_options={},
|
||||
use_mi_mode=True
|
||||
)
|
||||
|
||||
startup_timeout = self._get_timeout("timeouts", "gdb_start", 30)
|
||||
@ -98,28 +88,39 @@ class SymbolAnalyzer:
|
||||
log_progress(f"GDB Version: {analysis_data_dict['gdb_version_info']}")
|
||||
|
||||
set_status("Fetching function list..."); log_progress("Fetching function list from GDB...")
|
||||
# Diamo più tempo per 'info functions' in caso di librerie grandi
|
||||
functions = self._temp_gdb_session.list_functions(timeout=command_timeout * 4)
|
||||
analysis_data_dict["symbols"]["functions"] = functions
|
||||
analysis_data_dict["symbols"]["functions_count"] = len(functions)
|
||||
log_progress(f"Found {len(functions)} functions.")
|
||||
|
||||
# --- In future iterations, add calls for other symbol types (variables, types, sources) ---
|
||||
# set_status("Fetching global variables..."); log_progress("Fetching global variables...")
|
||||
# global_vars = self._temp_gdb_session.list_global_variables(timeout=command_timeout * 2)
|
||||
# analysis_data_dict["symbols"]["global_variables"] = global_vars
|
||||
# analysis_data_dict["symbols"]["global_variables_count"] = len(global_vars)
|
||||
# log_progress(f"Found {len(global_vars)} global variables.")
|
||||
# ... (similarly for types and source_files) ...
|
||||
# --- NUOVO: Recupera variabili globali ---
|
||||
set_status("Fetching global variables..."); log_progress("Fetching global variables from GDB...")
|
||||
global_variables = self._temp_gdb_session.list_global_variables(timeout=command_timeout * 2)
|
||||
analysis_data_dict["symbols"]["global_variables"] = global_variables
|
||||
analysis_data_dict["symbols"]["global_variables_count"] = len(global_variables)
|
||||
log_progress(f"Found {len(global_variables)} global variables.")
|
||||
|
||||
# --- NUOVO: Recupera tipi ---
|
||||
set_status("Fetching data types..."); log_progress("Fetching data types from GDB...")
|
||||
types = self._temp_gdb_session.list_types(timeout=command_timeout * 2)
|
||||
analysis_data_dict["symbols"]["types"] = types
|
||||
analysis_data_dict["symbols"]["types_count"] = len(types)
|
||||
log_progress(f"Found {len(types)} types.")
|
||||
|
||||
# --- Placeholder per futura iterazione: file sorgente ---
|
||||
# set_status("Fetching source files..."); log_progress("Fetching source files from GDB...")
|
||||
# source_files = self._temp_gdb_session.list_source_files(timeout=command_timeout * 2)
|
||||
# analysis_data_dict["symbols"]["source_files"] = source_files
|
||||
# analysis_data_dict["symbols"]["source_files_count"] = len(source_files)
|
||||
# log_progress(f"Found {len(source_files)} source files.")
|
||||
|
||||
|
||||
set_status("Calculating file checksum and timestamp..."); log_progress("Calculating file checksum and timestamp...")
|
||||
# Utilizza la funzione esterna calculate_file_checksum
|
||||
analysis_data_dict["executable_checksum"] = calculate_file_checksum(target_exe_path)
|
||||
try:
|
||||
mtime = os.path.getmtime(target_exe_path)
|
||||
analysis_data_dict["executable_timestamp"] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(mtime))
|
||||
except OSError: pass # Se il file non esiste (già controllato), o permessi. Lascia N/A
|
||||
except OSError: pass
|
||||
|
||||
log_progress(f"Checksum (MD5): {analysis_data_dict['executable_checksum'] or 'N/A'}")
|
||||
log_progress(f"File Timestamp: {analysis_data_dict['executable_timestamp']}")
|
||||
@ -133,7 +134,7 @@ class SymbolAnalyzer:
|
||||
logger.error(f"Error during symbol analysis for '{target_exe_path}': {e}", exc_info=True)
|
||||
log_progress(f"\nCRITICAL ERROR during analysis: {type(e).__name__} - {e}")
|
||||
set_status(f"Error during analysis: {e}")
|
||||
return {} # Ritorna un dizionario vuoto in caso di errore critico
|
||||
return {}
|
||||
finally:
|
||||
if self._temp_gdb_session and self._temp_gdb_session.is_alive():
|
||||
log_progress("Closing GDB session..."); set_status("Closing GDB session...")
|
||||
|
||||
@ -45,6 +45,7 @@ DEFAULT_PROFILE = {
|
||||
|
||||
|
||||
class ProfileManagerWindow(tk.Toplevel):
|
||||
# ... (__init__ come prima) ...
|
||||
def __init__(self, parent: 'GDBGui', app_settings: 'AppSettings'):
|
||||
super().__init__(parent)
|
||||
self.parent_window = parent
|
||||
@ -72,8 +73,8 @@ class ProfileManagerWindow(tk.Toplevel):
|
||||
|
||||
# StringVars per i conteggi
|
||||
self.functions_count_var = tk.StringVar(value="Functions: N/A")
|
||||
# self.variables_count_var = tk.StringVar(value="Globals: N/A") # Futuro
|
||||
# self.types_count_var = tk.StringVar(value="Types: N/A") # Futuro
|
||||
self.variables_count_var = tk.StringVar(value="Globals: N/A") # NUOVO
|
||||
self.types_count_var = tk.StringVar(value="Types: N/A") # NUOVO
|
||||
# self.sources_count_var = tk.StringVar(value="Sources: N/A") # Futuro
|
||||
|
||||
self._load_profiles_from_settings()
|
||||
@ -90,26 +91,6 @@ class ProfileManagerWindow(tk.Toplevel):
|
||||
self.target_exe_var.trace_add("write", lambda *args: self._on_target_exe_changed_in_form())
|
||||
self.program_params_var.trace_add("write", self._mark_form_as_modified)
|
||||
|
||||
def _mark_form_as_modified(self, *args):
|
||||
self._current_profile_modified_in_form = True
|
||||
|
||||
def _on_target_exe_changed_in_form(self, *args):
|
||||
self._mark_form_as_modified(*args)
|
||||
self._update_analysis_status_display()
|
||||
|
||||
def _load_profiles_from_settings(self) -> None:
|
||||
self._profiles_data = []
|
||||
loaded_profiles = self.app_settings.get_profiles()
|
||||
for profile_dict in loaded_profiles:
|
||||
copied_profile = json.loads(json.dumps(profile_dict)) # Deep copy
|
||||
if "actions" not in copied_profile or not isinstance(copied_profile["actions"], list):
|
||||
copied_profile["actions"] = []
|
||||
if "symbol_analysis" not in copied_profile:
|
||||
copied_profile["symbol_analysis"] = None
|
||||
self._profiles_data.append(copied_profile)
|
||||
self._profiles_list_changed_overall = False
|
||||
logger.debug(f"Loaded {len(self._profiles_data)} profiles into ProfileManagerWindow.")
|
||||
|
||||
def _create_widgets(self) -> None:
|
||||
main_frame = ttk.Frame(self, padding="10")
|
||||
main_frame.pack(expand=True, fill=tk.BOTH)
|
||||
@ -196,15 +177,20 @@ class ProfileManagerWindow(tk.Toplevel):
|
||||
self.view_functions_button.grid(row=row_s, column=1, padx=(10,5), pady=2, sticky="w")
|
||||
row_s += 1
|
||||
|
||||
# Placeholder per futuri conteggi e bottoni (Iterazione 3)
|
||||
# ttk.Label(symbols_summary_frame, textvariable=self.variables_count_var).grid(row=row_s, column=0, sticky="w", padx=5, pady=2)
|
||||
# self.view_variables_button = ttk.Button(symbols_summary_frame, text="View...", command=self._view_analyzed_variables, state=tk.DISABLED, width=8)
|
||||
# self.view_variables_button.grid(row=row_s, column=1, padx=(10,5), pady=2, sticky="w")
|
||||
# row_s += 1
|
||||
# ... (e così via per tipi e sorgenti)
|
||||
# --- NUOVI Conteggi e Bottoni View per Variabili Globali e Tipi ---
|
||||
ttk.Label(symbols_summary_frame, textvariable=self.variables_count_var).grid(row=row_s, column=0, sticky="w", padx=5, pady=2)
|
||||
self.view_variables_button = ttk.Button(symbols_summary_frame, text="View...", command=self._view_analyzed_variables, state=tk.DISABLED, width=8)
|
||||
self.view_variables_button.grid(row=row_s, column=1, padx=(10,5), pady=2, sticky="w")
|
||||
row_s += 1
|
||||
|
||||
ttk.Label(symbols_summary_frame, textvariable=self.types_count_var).grid(row=row_s, column=0, sticky="w", padx=5, pady=2)
|
||||
self.view_types_button = ttk.Button(symbols_summary_frame, text="View...", command=self._view_analyzed_types, state=tk.DISABLED, width=8)
|
||||
self.view_types_button.grid(row=row_s, column=1, padx=(10,5), pady=2, sticky="w")
|
||||
row_s += 1
|
||||
# --- FINE NUOVI Widget ---
|
||||
|
||||
actions_ui_frame = ttk.LabelFrame(right_pane, text="Debug Actions", padding="10")
|
||||
actions_ui_frame.grid(row=3, column=0, sticky="nsew", pady=5) # Riga 3
|
||||
actions_ui_frame.grid(row=3, column=0, sticky="nsew", pady=5)
|
||||
actions_ui_frame.rowconfigure(0, weight=1)
|
||||
actions_ui_frame.columnconfigure(0, weight=1)
|
||||
actions_ui_frame.columnconfigure(1, weight=0)
|
||||
@ -391,6 +377,31 @@ class ProfileManagerWindow(tk.Toplevel):
|
||||
logger.info(f"Profile '{profile_name}' (index {profile_index}) basic details updated.")
|
||||
return True
|
||||
|
||||
def _load_profiles_from_settings(self) -> None:
|
||||
"""
|
||||
Loads profiles from application settings into the internal _profiles_data list.
|
||||
Ensures deep copy and initializes new keys like 'symbol_analysis' if missing.
|
||||
"""
|
||||
self._profiles_data = []
|
||||
loaded_profiles = self.app_settings.get_profiles() # Questo restituisce una copia
|
||||
for profile_dict in loaded_profiles:
|
||||
# Effettua una deep copy robusta del dizionario del profilo per evitare modifiche dirette
|
||||
# ai dati dell'AppSettings fino al salvataggio esplicito.
|
||||
copied_profile = json.loads(json.dumps(profile_dict))
|
||||
|
||||
# Assicura che le chiavi necessarie esistano per la struttura del profilo,
|
||||
# fornendo valori di default se mancanti.
|
||||
if "actions" not in copied_profile or not isinstance(copied_profile["actions"], list):
|
||||
copied_profile["actions"] = []
|
||||
|
||||
if "symbol_analysis" not in copied_profile:
|
||||
copied_profile["symbol_analysis"] = None # Inizializza la chiave di analisi simboli
|
||||
|
||||
self._profiles_data.append(copied_profile)
|
||||
|
||||
self._profiles_list_changed_overall = False # Reset della flag di modifica complessiva
|
||||
logger.debug(f"Loaded {len(self._profiles_data)} profiles into ProfileManagerWindow.")
|
||||
|
||||
def _new_profile(self) -> None:
|
||||
if self._selected_profile_index is not None and self._current_profile_modified_in_form:
|
||||
response = messagebox.askyesnocancel("Unsaved Changes",
|
||||
@ -447,6 +458,10 @@ class ProfileManagerWindow(tk.Toplevel):
|
||||
self._select_profile_by_index(len(self._profiles_data) - 1)
|
||||
self._mark_form_as_modified()
|
||||
|
||||
def _mark_form_as_modified(self, *args):
|
||||
"""Callback to mark the current profile form as modified when a StringVar is changed."""
|
||||
self._current_profile_modified_in_form = True
|
||||
|
||||
def _delete_profile(self) -> None:
|
||||
if self._selected_profile_index is None or not self._profiles_data: return
|
||||
|
||||
@ -652,6 +667,10 @@ class ProfileManagerWindow(tk.Toplevel):
|
||||
self.analyse_symbols_button.config(state=tk.DISABLED)
|
||||
self.functions_count_var.set("Functions: N/A")
|
||||
self.view_functions_button.config(state=tk.DISABLED)
|
||||
self.variables_count_var.set("Globals: N/A") # Reset
|
||||
self.view_variables_button.config(state=tk.DISABLED) # Reset
|
||||
self.types_count_var.set("Types: N/A") # Reset
|
||||
self.view_types_button.config(state=tk.DISABLED) # Reset
|
||||
return
|
||||
|
||||
profile = self._profiles_data[self._selected_profile_index]
|
||||
@ -661,8 +680,14 @@ class ProfileManagerWindow(tk.Toplevel):
|
||||
details_text_lines = [f"Target in Form: {exe_display_name}"]
|
||||
status_text = "Symbol Analysis: "
|
||||
status_color = "blue"
|
||||
|
||||
# Inizializza tutti i conteggi a N/A e bottoni View a DISABLED
|
||||
funcs_count_text = "Functions: N/A"
|
||||
view_funcs_btn_state = tk.DISABLED
|
||||
vars_count_text = "Globals: N/A"
|
||||
view_vars_btn_state = tk.DISABLED
|
||||
types_count_text = "Types: N/A"
|
||||
view_types_btn_state = tk.DISABLED
|
||||
|
||||
analysis_button_state = tk.DISABLED
|
||||
if target_exe_in_form and os.path.isfile(target_exe_in_form):
|
||||
@ -677,10 +702,19 @@ class ProfileManagerWindow(tk.Toplevel):
|
||||
analysis_data = profile.get("symbol_analysis")
|
||||
if analysis_data and isinstance(analysis_data, dict):
|
||||
symbols_dict = analysis_data.get("symbols", {})
|
||||
|
||||
# Popola i conteggi e abilita i bottoni View se i dati ci sono
|
||||
num_functions = symbols_dict.get("functions_count", 0)
|
||||
funcs_count_text = f"Functions: {num_functions}"
|
||||
if num_functions > 0 :
|
||||
view_funcs_btn_state = tk.NORMAL
|
||||
if num_functions > 0 : view_funcs_btn_state = tk.NORMAL
|
||||
|
||||
num_variables = symbols_dict.get("global_variables_count", 0)
|
||||
vars_count_text = f"Globals: {num_variables}"
|
||||
if num_variables > 0 : view_vars_btn_state = tk.NORMAL
|
||||
|
||||
num_types = symbols_dict.get("types_count", 0)
|
||||
types_count_text = f"Types: {num_types}"
|
||||
if num_types > 0 : view_types_btn_state = tk.NORMAL
|
||||
|
||||
saved_checksum = analysis_data.get("executable_checksum")
|
||||
saved_analysis_ts_str = analysis_data.get("analysis_timestamp")
|
||||
@ -698,18 +732,24 @@ class ProfileManagerWindow(tk.Toplevel):
|
||||
if os.path.normpath(saved_exe_at_analysis) != os.path.normpath(target_exe_in_form):
|
||||
status_text += "TARGET CHANGED since last analysis. RE-ANALYSIS RECOMMENDED."
|
||||
status_color = "orange red"
|
||||
view_funcs_btn_state = tk.DISABLED
|
||||
view_funcs_btn_state = tk.DISABLED # Disabilita bottoni View se il target è cambiato
|
||||
view_vars_btn_state = tk.DISABLED
|
||||
view_types_btn_state = tk.DISABLED
|
||||
elif saved_checksum and current_checksum_for_form_exe and saved_checksum == current_checksum_for_form_exe:
|
||||
status_text += "Up-to-date."
|
||||
status_color = "dark green"
|
||||
elif saved_checksum and current_checksum_for_form_exe and saved_checksum != current_checksum_for_form_exe:
|
||||
status_text += "EXECUTABLE CHANGED since last analysis. RE-ANALYSIS REQUIRED."
|
||||
status_color = "red"
|
||||
view_funcs_btn_state = tk.DISABLED
|
||||
view_funcs_btn_state = tk.DISABLED # Disabilita bottoni View se l'eseguibile è cambiato
|
||||
view_vars_btn_state = tk.DISABLED
|
||||
view_types_btn_state = tk.DISABLED
|
||||
else:
|
||||
status_text += "Status unclear. Consider re-analysing."
|
||||
status_color = "orange red"
|
||||
view_funcs_btn_state = tk.DISABLED
|
||||
view_funcs_btn_state = tk.DISABLED # Disabilita bottoni View se lo stato è incerto
|
||||
view_vars_btn_state = tk.DISABLED
|
||||
view_types_btn_state = tk.DISABLED
|
||||
else:
|
||||
status_text += "Not performed. Click 'Analyse' to generate."
|
||||
status_color = "blue"
|
||||
@ -721,6 +761,10 @@ class ProfileManagerWindow(tk.Toplevel):
|
||||
|
||||
self.functions_count_var.set(funcs_count_text)
|
||||
self.view_functions_button.config(state=view_funcs_btn_state)
|
||||
self.variables_count_var.set(vars_count_text) # Aggiorna
|
||||
self.view_variables_button.config(state=view_vars_btn_state) # Aggiorna
|
||||
self.types_count_var.set(types_count_text) # Aggiorna
|
||||
self.view_types_button.config(state=view_types_btn_state) # Aggiorna
|
||||
|
||||
def _trigger_symbol_analysis(self) -> None:
|
||||
if self._selected_profile_index is None:
|
||||
@ -742,7 +786,6 @@ class ProfileManagerWindow(tk.Toplevel):
|
||||
|
||||
self.progress_dialog = SymbolAnalysisProgressDialog(self)
|
||||
|
||||
# Crea l'istanza di SymbolAnalyzer
|
||||
symbol_analyzer = SymbolAnalyzer(gdb_exe_path, self.app_settings)
|
||||
|
||||
analysis_thread = threading.Thread(
|
||||
@ -753,10 +796,10 @@ class ProfileManagerWindow(tk.Toplevel):
|
||||
analysis_thread.start()
|
||||
|
||||
def _perform_symbol_analysis_thread(self, profile_to_update: Dict[str, Any],
|
||||
target_exe_path: str, symbol_analyzer: SymbolAnalyzer, # Ora prende SymbolAnalyzer
|
||||
target_exe_path: str, symbol_analyzer: SymbolAnalyzer,
|
||||
progress_dialog: SymbolAnalysisProgressDialog):
|
||||
|
||||
analysis_data_dict: Dict[str, Any] = {} # Sarà popolato da SymbolAnalyzer.analyze()
|
||||
analysis_data_dict: Dict[str, Any] = {}
|
||||
analysis_succeeded_overall = False
|
||||
|
||||
def gui_log(msg: str):
|
||||
@ -771,14 +814,13 @@ class ProfileManagerWindow(tk.Toplevel):
|
||||
gui_log(f"Starting symbol analysis for: {os.path.basename(target_exe_path)}")
|
||||
gui_set_status(f"Analyzing {os.path.basename(target_exe_path)}...")
|
||||
|
||||
# Chiama il metodo analyze di SymbolAnalyzer
|
||||
analysis_data_dict = symbol_analyzer.analyze(
|
||||
target_exe_path=target_exe_path,
|
||||
progress_callback=gui_log,
|
||||
status_callback=gui_set_status
|
||||
)
|
||||
|
||||
if analysis_data_dict: # Se non è un dizionario vuoto (errore critico in SymbolAnalyzer)
|
||||
if analysis_data_dict:
|
||||
analysis_succeeded_overall = True
|
||||
gui_set_status("Symbol analysis successfully completed."); gui_log("\nSymbol analysis successfully completed.")
|
||||
else:
|
||||
@ -813,6 +855,7 @@ class ProfileManagerWindow(tk.Toplevel):
|
||||
|
||||
self._update_analysis_status_display()
|
||||
|
||||
# --- Metodi per Visualizzare Simboli Analizzati ---
|
||||
def _view_analyzed_functions(self) -> None:
|
||||
if self._selected_profile_index is None or \
|
||||
not (0 <= self._selected_profile_index < len(self._profiles_data)):
|
||||
@ -846,3 +889,63 @@ class ProfileManagerWindow(tk.Toplevel):
|
||||
dialog_title = f"Analyzed Functions for '{exe_name_for_title}'{title_suffix}"
|
||||
|
||||
SymbolListViewerDialog(self, functions_list, title=dialog_title)
|
||||
|
||||
def _view_analyzed_variables(self) -> None: # NUOVO METODO PER VARIABILI GLOBALI
|
||||
if self._selected_profile_index is None or not (0 <= self._selected_profile_index < len(self._profiles_data)):
|
||||
messagebox.showinfo("Info", "No profile selected or data available.", parent=self)
|
||||
return
|
||||
profile = self._profiles_data[self._selected_profile_index]
|
||||
analysis_data = profile.get("symbol_analysis")
|
||||
if not analysis_data or not isinstance(analysis_data.get("symbols"), dict):
|
||||
messagebox.showinfo("No Analysis Data", "No symbol analysis data available for this profile.", parent=self)
|
||||
return
|
||||
variables_list = analysis_data["symbols"].get("global_variables", [])
|
||||
if not variables_list:
|
||||
messagebox.showinfo("No Global Variables", "No global variables found in the last analysis for this profile.", parent=self)
|
||||
return
|
||||
|
||||
target_exe_in_form = self.target_exe_var.get()
|
||||
analyzed_exe_path = analysis_data.get("analyzed_executable_path", "")
|
||||
exe_name_for_title = os.path.basename(target_exe_in_form) if target_exe_in_form else "Unknown Executable"
|
||||
|
||||
is_obsolete = True
|
||||
if os.path.normpath(analyzed_exe_path) == os.path.normpath(target_exe_in_form):
|
||||
current_checksum = file_utils.calculate_file_checksum(target_exe_in_form)
|
||||
saved_checksum = analysis_data.get("executable_checksum")
|
||||
if current_checksum and saved_checksum and current_checksum == saved_checksum:
|
||||
is_obsolete = False
|
||||
|
||||
title_suffix = " (Analysis might be obsolete)" if is_obsolete else ""
|
||||
dialog_title = f"Analyzed Global Variables for '{exe_name_for_title}'{title_suffix}"
|
||||
|
||||
SymbolListViewerDialog(self, variables_list, title=dialog_title)
|
||||
|
||||
def _view_analyzed_types(self) -> None: # NUOVO METODO PER TIPI
|
||||
if self._selected_profile_index is None or not (0 <= self._selected_profile_index < len(self._profiles_data)):
|
||||
messagebox.showinfo("Info", "No profile selected or data available.", parent=self)
|
||||
return
|
||||
profile = self._profiles_data[self._selected_profile_index]
|
||||
analysis_data = profile.get("symbol_analysis")
|
||||
if not analysis_data or not isinstance(analysis_data.get("symbols"), dict):
|
||||
messagebox.showinfo("No Analysis Data", "No symbol analysis data available for this profile.", parent=self)
|
||||
return
|
||||
types_list = analysis_data["symbols"].get("types", [])
|
||||
if not types_list:
|
||||
messagebox.showinfo("No Types", "No types found in the last analysis for this profile.", parent=self)
|
||||
return
|
||||
|
||||
target_exe_in_form = self.target_exe_var.get()
|
||||
analyzed_exe_path = analysis_data.get("analyzed_executable_path", "")
|
||||
exe_name_for_title = os.path.basename(target_exe_in_form) if target_exe_in_form else "Unknown Executable"
|
||||
|
||||
is_obsolete = True
|
||||
if os.path.normpath(analyzed_exe_path) == os.path.normpath(target_exe_in_form):
|
||||
current_checksum = file_utils.calculate_file_checksum(target_exe_in_form)
|
||||
saved_checksum = analysis_data.get("executable_checksum")
|
||||
if current_checksum and saved_checksum and current_checksum == saved_checksum:
|
||||
is_obsolete = False
|
||||
|
||||
title_suffix = " (Analysis might be obsolete)" if is_obsolete else ""
|
||||
dialog_title = f"Analyzed Types for '{exe_name_for_title}'{title_suffix}"
|
||||
|
||||
SymbolListViewerDialog(self, types_list, title=dialog_title)
|
||||
Loading…
Reference in New Issue
Block a user