llvm-project/lldb/docs/use/tutorials/custom-frame-recognizers.md
David Spickett 870aa89fbc [lldb][docs] Remove syntax hint from some output blocks
This tries to parse the block as that language but in these
cases fails because they aren't purely that language. This
falls back to a permissive mode which is fine, but highlights
the invalid tokens like errors which isn't great.

Instead don't try to highlight these blocks. This fixes 4
warnings seen in the docs build:
lldb/docs/use/tutorials/custom-frame-recognizers.md:43: WARNING: Lexing literal_block <...> as "c++" resulted in an error at token: '#'. Retrying in relaxed mode.
lldb/docs/use/tutorials/script-driven-debugging.md:175: WARNING: Lexing literal_block <...> as "c++" resulted in an error at token: '#'. Retrying in relaxed mode.
lldb/docs/use/tutorials/script-driven-debugging.md:426: WARNING: Lexing literal_block <...> as "c++" resulted in an error at token: '#'. Retrying in relaxed mode.
lldb/docs/use/tutorials/writing-custom-commands.md:416: WARNING: Lexing literal_block <...> as "python3" resulted in an error at token: '$'. Retrying in relaxed mode.
2025-12-09 12:41:19 +00:00

2.0 KiB

Detecting Patterns With Recognizers

Frame recognizers allow for retrieving information about special frames based on ABI, arguments or other special properties of that frame, even without source code or debug info. Currently, one use case is to extract function arguments that would otherwise be inaccessible, or augment existing arguments.

Adding a custom frame recognizer is done by implementing a Python class and using the frame recognizer add command. The Python class should implement the get_recognized_arguments method and it will receive an argument of type lldb.SBFrame representing the current frame that we are trying to recognize. The method should return a (possibly empty) list of lldb.SBValue objects that represent the recognized arguments.

An example of a recognizer that retrieves the file descriptor values from libc functions 'read', 'write' and 'close' follows:

class LibcFdRecognizer:
  def get_recognized_arguments(self, frame: lldb.SBFrame):
    if frame.name in ["read", "write", "close"]:
      fd = frame.EvaluateExpression("$arg1").unsigned
      target = frame.thread.process.target
      value = target.CreateValueFromExpression("fd", "(int)%d" % fd)
      return [value]
    return []

The file containing this implementation can be imported via command script import and then we can register this recognizer with frame recognizer add.

It's important to restrict the recognizer to the libc library (which is libsystem_kernel.dylib on macOS) to avoid matching functions with the same name in other modules:

(lldb) command script import .../fd_recognizer.py
(lldb) frame recognizer add -l fd_recognizer.LibcFdRecognizer -n read -s libsystem_kernel.dylib

When the program is stopped at the beginning of the 'read' function in libc, we can view the recognizer arguments in 'frame variable':

(lldb) b read
(lldb) r
Process 1234 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.3
    frame #0: 0x00007fff06013ca0 libsystem_kernel.dylib`read
(lldb) frame variable
(int) fd = 3