Skip to content

Commit ce68592

Browse files
committed
Bug fixes
1 parent dc223c8 commit ce68592

File tree

2 files changed

+67
-21
lines changed

2 files changed

+67
-21
lines changed

plugin/ida_mcp_server_plugin/ida_mcp_core.py

Lines changed: 64 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ def get_function_assembly_by_name(self, function_name: str) -> Dict[str, Any]:
128128
return {"error": f"Function '{function_name}' not found"}
129129

130130
# Call address-based implementation
131-
result = self.get_function_assembly_by_address(func.start_ea)
131+
result = self._get_function_assembly_by_address_internal(func.start_ea)
132132

133133
# If successful, add function name to result
134134
if "error" not in result:
@@ -142,6 +142,10 @@ def get_function_assembly_by_name(self, function_name: str) -> Dict[str, Any]:
142142
@idaread
143143
def get_function_assembly_by_address(self, address: int) -> Dict[str, Any]:
144144
"""Get assembly code for a function by its address"""
145+
return self._get_function_assembly_by_address_internal(address)
146+
147+
def _get_function_assembly_by_address_internal(self, address: int) -> Dict[str, Any]:
148+
"""Internal implementation for get_function_assembly_by_address without sync wrapper"""
145149
try:
146150
# Get function from address
147151
func = idaapi.get_func(address)
@@ -196,8 +200,8 @@ def get_function_decompiled_by_name(self, function_name: str) -> Dict[str, Any]:
196200
if func_addr == idaapi.BADADDR:
197201
return {"error": f"Function '{function_name}' not found"}
198202

199-
# Call address-based implementation
200-
result = self.get_function_decompiled_by_address(func_addr)
203+
# Call internal implementation without decorator
204+
result = self._get_function_decompiled_by_address_internal(func_addr)
201205

202206
# If successful, add function name to result
203207
if "error" not in result:
@@ -211,6 +215,10 @@ def get_function_decompiled_by_name(self, function_name: str) -> Dict[str, Any]:
211215
@idaread
212216
def get_function_decompiled_by_address(self, address: int) -> Dict[str, Any]:
213217
"""Get decompiled code for a function by its address"""
218+
return self._get_function_decompiled_by_address_internal(address)
219+
220+
def _get_function_decompiled_by_address_internal(self, address: int) -> Dict[str, Any]:
221+
"""Internal implementation for get_function_decompiled_by_address without sync wrapper"""
214222
try:
215223
# Get function from address
216224
func = idaapi.get_func(address)
@@ -257,8 +265,8 @@ def get_current_function_assembly(self) -> Dict[str, Any]:
257265
if curr_addr == idaapi.BADADDR:
258266
return {"error": "No valid cursor position"}
259267

260-
# Use the address-based implementation
261-
return self.get_function_assembly_by_address(curr_addr)
268+
# Use the internal implementation without decorator
269+
return self._get_function_assembly_by_address_internal(curr_addr)
262270
except Exception as e:
263271
traceback.print_exc()
264272
return {"error": str(e)}
@@ -272,8 +280,8 @@ def get_current_function_decompiled(self) -> Dict[str, Any]:
272280
if curr_addr == idaapi.BADADDR:
273281
return {"error": "No valid cursor position"}
274282

275-
# Use the address-based implementation
276-
return self.get_function_decompiled_by_address(curr_addr)
283+
# Use the internal implementation without decorator
284+
return self._get_function_decompiled_by_address_internal(curr_addr)
277285
except Exception as e:
278286
traceback.print_exc()
279287
return {"error": str(e)}
@@ -287,8 +295,8 @@ def get_global_variable_by_name(self, variable_name: str) -> Dict[str, Any]:
287295
if var_addr == idaapi.BADADDR:
288296
return {"error": f"Global variable '{variable_name}' not found"}
289297

290-
# Call address-based implementation
291-
result = self.get_global_variable_by_address(var_addr)
298+
# Call internal implementation
299+
result = self._get_global_variable_by_address_internal(var_addr)
292300

293301
# If successful, add variable name to result
294302
if "error" not in result and "variable_info" in result:
@@ -307,6 +315,10 @@ def get_global_variable_by_name(self, variable_name: str) -> Dict[str, Any]:
307315
@idaread
308316
def get_global_variable_by_address(self, address: int) -> Dict[str, Any]:
309317
"""Get global variable information by its address"""
318+
return self._get_global_variable_by_address_internal(address)
319+
320+
def _get_global_variable_by_address_internal(self, address: int) -> Dict[str, Any]:
321+
"""Internal implementation for get_global_variable_by_address without sync wrapper"""
310322
try:
311323
# Verify address is valid
312324
if address == idaapi.BADADDR:
@@ -375,6 +387,10 @@ def get_global_variable_by_address(self, address: int) -> Dict[str, Any]:
375387
@idawrite
376388
def rename_global_variable(self, old_name: str, new_name: str) -> Dict[str, Any]:
377389
"""Rename a global variable"""
390+
return self._rename_global_variable_internal(old_name, new_name)
391+
392+
def _rename_global_variable_internal(self, old_name: str, new_name: str) -> Dict[str, Any]:
393+
"""Internal implementation for rename_global_variable without sync wrapper"""
378394
try:
379395
# Get variable address
380396
var_addr: int = ida_name.get_name_ea(0, old_name)
@@ -390,7 +406,7 @@ def rename_global_variable(self, old_name: str, new_name: str) -> Dict[str, Any]
390406
return {"success": False, "message": f"Failed to rename variable, possibly due to invalid name format or other IDA restrictions"}
391407

392408
# Refresh view
393-
self.refresh_view_internal()
409+
self._refresh_view_internal()
394410

395411
return {"success": True, "message": f"Variable renamed from '{old_name}' to '{new_name}' at address {hex(var_addr)}"}
396412

@@ -402,6 +418,10 @@ def rename_global_variable(self, old_name: str, new_name: str) -> Dict[str, Any]
402418
@idawrite
403419
def rename_function(self, old_name: str, new_name: str) -> Dict[str, Any]:
404420
"""Rename a function"""
421+
return self._rename_function_internal(old_name, new_name)
422+
423+
def _rename_function_internal(self, old_name: str, new_name: str) -> Dict[str, Any]:
424+
"""Internal implementation for rename_function without sync wrapper"""
405425
try:
406426
# Get function address
407427
func_addr: int = ida_name.get_name_ea(0, old_name)
@@ -422,7 +442,7 @@ def rename_function(self, old_name: str, new_name: str) -> Dict[str, Any]:
422442
return {"success": False, "message": f"Failed to rename function, possibly due to invalid name format or other IDA restrictions"}
423443

424444
# Refresh view
425-
self.refresh_view_internal()
445+
self._refresh_view_internal()
426446

427447
return {"success": True, "message": f"Function renamed from '{old_name}' to '{new_name}' at address {hex(func_addr)}"}
428448

@@ -434,6 +454,10 @@ def rename_function(self, old_name: str, new_name: str) -> Dict[str, Any]:
434454
@idawrite
435455
def add_assembly_comment(self, address: str, comment: str, is_repeatable: bool) -> Dict[str, Any]:
436456
"""Add an assembly comment"""
457+
return self._add_assembly_comment_internal(address, comment, is_repeatable)
458+
459+
def _add_assembly_comment_internal(self, address: str, comment: str, is_repeatable: bool) -> Dict[str, Any]:
460+
"""Internal implementation for add_assembly_comment without sync wrapper"""
437461
try:
438462
# Convert address string to integer
439463
addr: int
@@ -459,7 +483,7 @@ def add_assembly_comment(self, address: str, comment: str, is_repeatable: bool)
459483
result: bool = idc.set_cmt(addr, comment, is_repeatable)
460484
if result:
461485
# Refresh view
462-
self.refresh_view_internal()
486+
self._refresh_view_internal()
463487
comment_type: str = "repeatable" if is_repeatable else "regular"
464488
return {"success": True, "message": f"Added {comment_type} assembly comment at address {hex(addr)}"}
465489
else:
@@ -473,6 +497,10 @@ def add_assembly_comment(self, address: str, comment: str, is_repeatable: bool)
473497
@idawrite
474498
def rename_local_variable(self, function_name: str, old_name: str, new_name: str) -> Dict[str, Any]:
475499
"""Rename a local variable within a function"""
500+
return self._rename_local_variable_internal(function_name, old_name, new_name)
501+
502+
def _rename_local_variable_internal(self, function_name: str, old_name: str, new_name: str) -> Dict[str, Any]:
503+
"""Internal implementation for rename_local_variable without sync wrapper"""
476504
try:
477505
# Parameter validation
478506
if not function_name:
@@ -526,7 +554,7 @@ def rename_local_variable(self, function_name: str, old_name: str, new_name: str
526554

527555
if renamed:
528556
# Refresh view
529-
self.refresh_view_internal()
557+
self._refresh_view_internal()
530558
return {"success": True, "message": f"Local variable renamed from '{old_name}' to '{new_name}' in function '{function_name}'"}
531559
else:
532560
return {"success": False, "message": f"Failed to rename local variable from '{old_name}' to '{new_name}', possibly due to invalid name format or other IDA restrictions"}
@@ -539,6 +567,10 @@ def rename_local_variable(self, function_name: str, old_name: str, new_name: str
539567
@idawrite
540568
def add_function_comment(self, function_name: str, comment: str, is_repeatable: bool) -> Dict[str, Any]:
541569
"""Add a comment to a function"""
570+
return self._add_function_comment_internal(function_name, comment, is_repeatable)
571+
572+
def _add_function_comment_internal(self, function_name: str, comment: str, is_repeatable: bool) -> Dict[str, Any]:
573+
"""Internal implementation for add_function_comment without sync wrapper"""
542574
try:
543575
# Parameter validation
544576
if not function_name:
@@ -567,7 +599,7 @@ def add_function_comment(self, function_name: str, comment: str, is_repeatable:
567599

568600
if result:
569601
# Refresh view
570-
self.refresh_view_internal()
602+
self._refresh_view_internal()
571603
comment_type: str = "repeatable" if is_repeatable else "regular"
572604
return {"success": True, "message": f"Added {comment_type} comment to function '{function_name}'"}
573605
else:
@@ -581,6 +613,10 @@ def add_function_comment(self, function_name: str, comment: str, is_repeatable:
581613
@idawrite
582614
def add_pseudocode_comment(self, function_name: str, address: str, comment: str, is_repeatable: bool) -> Dict[str, Any]:
583615
"""Add a comment to a specific address in the function's decompiled pseudocode"""
616+
return self._add_pseudocode_comment_internal(function_name, address, comment, is_repeatable)
617+
618+
def _add_pseudocode_comment_internal(self, function_name: str, address: str, comment: str, is_repeatable: bool) -> Dict[str, Any]:
619+
"""Internal implementation for add_pseudocode_comment without sync wrapper"""
584620
try:
585621
# Parameter validation
586622
if not function_name:
@@ -647,7 +683,7 @@ def add_pseudocode_comment(self, function_name: str, address: str, comment: str,
647683
cfunc.save_user_cmts()
648684

649685
# Refresh view
650-
self.refresh_view_internal()
686+
self._refresh_view_internal()
651687

652688
comment_type: str = "repeatable" if is_repeatable else "regular"
653689
return {
@@ -663,9 +699,9 @@ def add_pseudocode_comment(self, function_name: str, address: str, comment: str,
663699
@idawrite
664700
def refresh_view(self) -> Dict[str, Any]:
665701
"""Refresh IDA Pro view"""
666-
return self.refresh_view_internal()
702+
return self._refresh_view_internal()
667703

668-
def refresh_view_internal(self) -> Dict[str, Any]:
704+
def _refresh_view_internal(self) -> Dict[str, Any]:
669705
"""Implementation of refreshing view in IDA main thread"""
670706
try:
671707
# Refresh disassembly view
@@ -699,6 +735,10 @@ def refresh_view_internal(self) -> Dict[str, Any]:
699735
@idawrite
700736
def execute_script(self, script: str) -> Dict[str, Any]:
701737
"""Execute a Python script in IDA context"""
738+
return self._execute_script_internal(script)
739+
740+
def _execute_script_internal(self, script: str) -> Dict[str, Any]:
741+
"""Internal implementation for execute_script without sync wrapper"""
702742
try:
703743
print(f"Executing script, length: {len(script) if script else 0}")
704744

@@ -860,7 +900,7 @@ def execute_script(self, script: str) -> Dict[str, Any]:
860900

861901
# Refresh view to show any changes made by script
862902
print("Refreshing view")
863-
self.refresh_view_internal()
903+
self._refresh_view_internal()
864904
except Exception as e:
865905
print(f"Error in execute_script outer scope: {str(e)}")
866906
traceback.print_exc()
@@ -875,6 +915,10 @@ def execute_script(self, script: str) -> Dict[str, Any]:
875915
@idawrite
876916
def execute_script_from_file(self, file_path: str) -> Dict[str, Any]:
877917
"""Execute a Python script from a file in IDA context"""
918+
return self._execute_script_from_file_internal(file_path)
919+
920+
def _execute_script_from_file_internal(self, file_path: str) -> Dict[str, Any]:
921+
"""Internal implementation for execute_script_from_file without sync wrapper"""
878922
try:
879923
# Check if file path is provided
880924
if not file_path or not file_path.strip():
@@ -902,8 +946,8 @@ def execute_script_from_file(self, file_path: str) -> Dict[str, Any]:
902946
with open(file_path, 'r') as f:
903947
script = f.read()
904948

905-
# Execute script
906-
return self.execute_script(script)
949+
# Execute script using internal method
950+
return self._execute_script_internal(script)
907951
except Exception as file_error:
908952
print(f"Error reading or executing script file: {str(file_error)}")
909953
traceback.print_exc()

test/IDA Debug.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,7 @@
1515
# idapro.open_database("/Volumes/FrameworkLab/Dyld-Shared-Cache/macOS/15.1/dyld_shared_cache_arm64e-LaunchServices.i64", True) # 替换为你的数据库路径
1616

1717
core = IDAMCPCore()
18-
print(core.execute_script("import idautils\nimport idc\n\ncurrent_ea = idc.here()\ncurrent_func = idc.get_func_name(current_ea)\n\nif current_func:\n print(f'当前函数名: {current_func}')\n func_addr = idc.get_name_ea_simple(current_func)\n print(f'函数地址: {hex(func_addr)}')\n \n print('\\n引用此函数的位置:')\n for xref in idautils.XrefsTo(func_addr):\n print(f'从地址 {hex(xref.frm)} 引用')\n \n print('\\n此函数引用的位置:')\n for addr in idautils.FuncItems(func_addr):\n for xref in idautils.XrefsFrom(addr):\n print(f'在地址 {hex(addr)} 引用了 {hex(xref.to)}')\nelse:\n print('错误:未能获取当前函数')"))
18+
# print(core.execute_script("import idautils\nimport idc\n\ncurrent_ea = idc.here()\ncurrent_func = idc.get_func_name(current_ea)\n\nif current_func:\n print(f'当前函数名: {current_func}')\n func_addr = idc.get_name_ea_simple(current_func)\n print(f'函数地址: {hex(func_addr)}')\n \n print('\\n引用此函数的位置:')\n for xref in idautils.XrefsTo(func_addr):\n print(f'从地址 {hex(xref.frm)} 引用')\n \n print('\\n此函数引用的位置:')\n for addr in idautils.FuncItems(func_addr):\n for xref in idautils.XrefsFrom(addr):\n print(f'在地址 {hex(addr)} 引用了 {hex(xref.to)}')\nelse:\n print('错误:未能获取当前函数')"))
19+
print(core.get_current_function_decompiled())
20+
print(core.get_function_decompiled_by_name("-[SPSpotlightPanel canBecomeMainWindow]"))
1921
# idapro.close_database()

0 commit comments

Comments
 (0)