@@ -331,9 +331,16 @@ def _execute_mi(self, cmd: str, timeout: float = GDB_CMD_TIMEOUT) -> Optional[st
331331
332332 def _execute_cli (self , cmd : str , timeout : float = GDB_CMD_TIMEOUT ) -> Optional [str ]:
333333 """Execute a GDB CLI command and return console output lines."""
334+ t0 = time .time ()
334335 raw = self ._execute_mi (cmd , timeout )
336+ elapsed = time .time () - t0
335337 if raw is None :
338+ logger .warning (f"[GDB] command timed out ({ elapsed :.2f} s): { cmd } " )
336339 return None
340+ if elapsed > 1.0 :
341+ logger .warning (f"[GDB] slow command ({ elapsed :.2f} s): { cmd } " )
342+ else :
343+ logger .debug (f"[GDB] command ({ elapsed :.3f} s): { cmd } " )
337344 return self ._extract_console_output (raw )
338345
339346 def _read_until_prompt (self , timeout : float = 5.0 ) -> Optional [str ]:
@@ -415,13 +422,20 @@ def _extract_console_output(raw: str) -> str:
415422
416423 def _lookup_symbol_impl (self , sym_name : str ) -> Optional [dict ]:
417424 """Internal implementation of lookup_symbol."""
425+ t_start = time .time ()
426+ logger .info (f"[GDB] lookup_symbol start: '{ sym_name } '" )
427+
418428 # Use 'info address' to get symbol address
419429 output = self ._execute_cli (f"info address { sym_name } " )
420430 if not output or "No symbol" in output :
431+ logger .info (f"[GDB] lookup_symbol: '{ sym_name } ' not found" )
421432 return None
422433
423434 addr = self ._parse_address_from_info (output )
424435 if addr is None :
436+ logger .warning (
437+ f"[GDB] lookup_symbol: cannot parse address for '{ sym_name } '"
438+ )
425439 return None
426440
427441 # Get size via 'print sizeof(sym_name)'
@@ -445,6 +459,12 @@ def _lookup_symbol_impl(self, sym_name: str) -> Optional[dict]:
445459 if ptype_out and re .match (r"type\s*=\s*const\b" , ptype_out ):
446460 sym_type = "const"
447461
462+ elapsed = time .time () - t_start
463+ logger .info (
464+ f"[GDB] lookup_symbol done: '{ sym_name } ' -> "
465+ f"0x{ addr :08X} size={ size } type={ sym_type } ({ elapsed :.3f} s)"
466+ )
467+
448468 return {
449469 "addr" : addr ,
450470 "size" : size ,
@@ -456,6 +476,8 @@ def _search_symbols_impl(
456476 self , query : str , limit : int = 100
457477 ) -> Tuple [List [dict ], int ]:
458478 """Internal implementation of search_symbols."""
479+ t_start = time .time ()
480+ logger .info (f"[GDB] search_symbols start: query='{ query } ' limit={ limit } " )
459481 query_lower = query .lower ().strip ()
460482 is_addr = query_lower .startswith ("0x" ) or (
461483 len (query_lower ) >= 4 and all (c in "0123456789abcdef" for c in query_lower )
@@ -498,10 +520,21 @@ def _search_symbols_impl(
498520 seen .add (r ["name" ])
499521 unique .append (r )
500522
523+ t_parse = time .time ()
524+ logger .info (
525+ f"[GDB] search_symbols: found { len (unique )} unique symbols, "
526+ f"resolving addresses... (parse took { t_parse - t_start :.3f} s)"
527+ )
528+
501529 # Resolve missing addresses via 'info address'
502530 self ._resolve_addresses (unique )
503531
504532 unique .sort (key = lambda x : x ["name" ])
533+ elapsed = time .time () - t_start
534+ logger .info (
535+ f"[GDB] search_symbols done: query='{ query } ' -> "
536+ f"{ len (unique )} results ({ elapsed :.3f} s)"
537+ )
505538 return unique [:limit ], len (unique )
506539
507540 def _get_symbols_impl (self ) -> Dict [str , dict ]:
@@ -551,15 +584,27 @@ def _get_struct_layout_impl(self, sym_name: str) -> Optional[List[dict]]:
551584
552585 Uses 'ptype /o <sym>' which shows struct members with offsets.
553586 """
587+ t0 = time .time ()
588+ logger .info (f"[GDB] get_struct_layout start: '{ sym_name } '" )
589+
554590 output = self ._execute_cli (f"ptype /o { sym_name } " )
555591 if not output :
592+ logger .info (f"[GDB] get_struct_layout: no output for '{ sym_name } '" )
556593 return None
557594
558595 # Check if it's a struct/union
559596 if "type = struct" not in output and "type = union" not in output :
597+ logger .info (f"[GDB] get_struct_layout: '{ sym_name } ' is not struct/union" )
560598 return None
561599
562- return self ._parse_ptype_output (output )
600+ result = self ._parse_ptype_output (output )
601+ elapsed = time .time () - t0
602+ member_count = len (result ) if result else 0
603+ logger .info (
604+ f"[GDB] get_struct_layout done: '{ sym_name } ' -> "
605+ f"{ member_count } members ({ elapsed :.3f} s)"
606+ )
607+ return result
563608
564609 def _read_symbol_value_impl (self , sym_name : str ) -> Optional [bytes ]:
565610 """Internal implementation of read_symbol_value.
@@ -627,6 +672,14 @@ def _resolve_addresses(self, symbols: List[dict]):
627672 addresses. This method queries 'info address <name>' for each symbol
628673 with addr "0x00000000" to fill in the real address and section.
629674 """
675+ unresolved = [s for s in symbols if s ["addr" ] == "0x00000000" ]
676+ if unresolved :
677+ logger .info (
678+ f"[GDB] _resolve_addresses: { len (unresolved )} /{ len (symbols )} "
679+ f"symbols need address resolution"
680+ )
681+ t0 = time .time ()
682+ resolved_count = 0
630683 for sym in symbols :
631684 if sym ["addr" ] != "0x00000000" :
632685 continue
@@ -636,6 +689,7 @@ def _resolve_addresses(self, symbols: List[dict]):
636689 addr = self ._parse_address_from_info (output )
637690 if addr is not None :
638691 sym ["addr" ] = f"0x{ addr :08X} "
692+ resolved_count += 1
639693 # Also fix section and type from info address output
640694 section = self ._get_symbol_section (output )
641695 if section :
@@ -650,6 +704,13 @@ def _resolve_addresses(self, symbols: List[dict]):
650704 # Preserve const classification from declaration
651705 sym ["type" ] = "variable"
652706
707+ if unresolved :
708+ elapsed = time .time () - t0
709+ logger .info (
710+ f"[GDB] _resolve_addresses done: resolved { resolved_count } /{ len (unresolved )} "
711+ f"({ elapsed :.3f} s)"
712+ )
713+
653714 @staticmethod
654715 def _parse_address_from_info (output : str ) -> Optional [int ]:
655716 """Parse address from 'info address' output.
0 commit comments