Python에서 C용 LLDB 사용자 정의 데이터 포맷 프로그램
소개하다.
LLDB 디버그 C나 C++ 프로그램을 사용하면 LLDB의 인쇄 (
p
) 명령의 출력을 기본값이 아닌 print the contents of variables in a more enlightening way으로 사용자 정의할 수 있습니다.너는 심지어 Python을 사용할 수 있다.그러나 내가 찾을 수 있는 examples은 거의 상대적으로 자질구레한 데이터 구조만 보였다.대량의 검색과 시도, 오류를 통해 나는 파이톤을 사용하여 평범하지 않은 struct
을 인쇄하는 방법을 찾았다.데이터 구조
인쇄하고 싶은 C 데이터 구조는 cdecl, the following을 포함하여 단일 체인 테이블(이 예에서 일부 조정됨)을 구현합니다.
typedef struct slist slist_t;
typedef struct slist_node slist_node_t;
struct slist {
slist_node_t *head; // Pointer to list head.
slist_node_t *tail; // Pointer to list tail.
};
struct slist_node {
slist_node_t *next; // Pointer to next node or null.
void *data; // Pointer to user data.
};
그런 다음 S::T
과 같이 C++ 범위의 이름을 저장하는 데 사용합니다.typedef struct slist c_sname_t; // C++ scoped name.
그 중에서 각 역할 영역의 이름은 slist_node
으로 저장되고 그 중에서 data
은 실제로는 c_scope_data*
이다. 그 중에서 c_scope_data
은 각 역할 영역에 대한 데이터를 포함하고 특히 그 이름은 다음과 같다.struct c_scope_data {
char const *name; // The scope's name.
// ...
};
S::T
의 경우 slist
은 두 개의 노드를 포함한다. 하나는 S
에 사용되고 다른 하나는 T
에 사용된다.LLDB에서
c_sname_t
의 변수를 디버깅하고 인쇄할 때, 나는 LLDB가 전체 작용 도메인 이름 S::T
을 인쇄하기를 희망한다. 즉, 각 노드의 이름 목록을 인쇄하는 것이지, head
자체의 tail
과 slist
바늘의 기본값만 인쇄하는 것이 아니다.LLDB Python 모듈
이를 위해 LLDB Python 모듈을 구현했습니다.이 모듈은 다음부터 시작합니다.
# cdecl_lldb.py
import lldb
def __lldb_init_module(debugger, internal_dict):
cmd_prefix = 'type summary add -F ' + __name__
debugger.HandleCommand(cmd_prefix + '.show_c_sname_t c_sname_t')
__lldb_init_module
은 LLDB
함수를 호출하여 모듈을 초기화합니다. 그 중에서 debugger
은 LLDB 자체의 실례이고 서명은 internal_dict
이 필요하지만 상호작용을 할 필요가 없습니다.이 함수를 사용하여 C 유형을 사용자 정의 포맷 프로그램에 바인딩할 수 있습니다.대사:
cmd_prefix = 'type summary add -F ' + __name__
debugger.HandleCommand(cmd_prefix + '.show_c_sname_t c_sname_t')
cmd_prefix
을 후속 줄에 사용할 줄임말(그중 __name__
은 현재 Python 파일의 이름이고 .py
확장자가 없음)으로 성명하였으며, HandleCommand
은 포맷 프로그램(-F
)을 show_c_sname_t
형식의 c_sname_t
함수에 귀속시켰다.(네, typedef
개 d명칭 가능합니다.)show_c_sname_t
을 실현하기 전에 우리는 데이터 구조를 두루 훑어보는 데 도움을 줄 실용 함수가 필요하다.def null(ptr):
"""Gets whether the SBValue is a NULL pointer."""
return not ptr.IsValid() or ptr.GetValueAsUnsigned() == 0
(SBValue
은 변수, 레지스터 또는 표현식의 내용을 저장하는 LLDB 데이터 구조입니다.)show_c_sname_t
의 구축 시작:def show_c_sname_t(c_sname, internal_dict):
colon2 = False # Print "::" scope separator?
rv = "" # "string-ified" value to return
c_sname_t
은 typedef
의 slist
이기 때문에 우리는 먼저 목록의 head
을 획득한 다음에 목록을 훑어보아야 한다.공교롭게도 SBValue
에는 linked_list_iter()
함수가 있는데 다음 지침을 포함하는 struct
의 구성원의 이름은 다음과 같다. head = c_sname.GetChildMemberWithName('head')
for slist_node_ptr in head.linked_list_iter('next'):
각 노드에 대해 data
의 구성원을 확보한 다음에 void*
을 c_scope_data_t*
으로 전환해야 한다.전환을 진행하려면 파이톤에서 c_scope_data_t*
형식을 가져와야 합니다.이 작업은 다음 방법으로 순환하기 전에 한 번 완료할 수 있습니다. target = lldb.debugger.GetSelectedTarget()
c_scope_data_ptr_t = target.FindFirstType('c_scope_data_t').GetPointerType()
이제 이 기능의 나머지 부분은 다음과 같습니다. head = c_sname.GetChildMemberWithName('head')
for slist_node_ptr in head.linked_list_iter('next'):
void_data_ptr = slist_node_ptr.GetChildMemberWithName('data')
if not null(void_data_ptr):
c_scope_data_ptr = void_data_ptr.Cast(c_scope_data_ptr_t)
name_ptr = c_scope_data_ptr.GetChildMemberWithName('name')
if not null(name_ptr):
if colon2:
rv += '::'
else:
colon2 = True
rv += name_ptr.GetSummary().strip('"')
return '"' + rv + '"'
name_ptr
을 지정하고, 우리는 GetSummary()
을 사용하여 실제 명칭 문자열을 가져옵니다.GetSummary()
은 결과 주위에 인용 부호를 붙인다. 우리는 모든 역할 영역의 이름이 아니라 전체 반환 값 주위에 인용 부호를 붙이기를 원하기 때문이다.로드 모듈
LLDB가 시작할 때마다 모듈을 불러오기 위해서 저는 먼저 cdecl의
.lldbinit
디렉터리에 src
파일을 만들었습니다.# .lldbinit
command script import cdecl_lldb.py
LLDB를 로드하려면 allow loading of .lldbinit
files from the current working directory이 필요합니다.이렇게 하려면 다음을 추가합니다.settings set target.load-cwd-lldbinit true
전 세계 ~/.lldbinit
파일대화식으로 Python 사용
올바른 Python을 생성하려고 시도할 때, 스크립트를 편집하고, 저장하고, LLDB를 시작하고, 인터럽트를 설정하고, 프로그램을 실행할 때마다 ("편집 - 컴파일 - 실행 순환"), LLDB에서 Python 해석기에 들어가서, 변수의 정확한 Python 코드를 인쇄할 수 있도록 반복 테스트를 할 수 있습니다.예를 들어, 다음 컨텐트가 포함된 함수를 지정합니다.
c_sname_t const *sname = find_name( /*...*/ );
do_something( sname );
do_something()
에서 인터럽트를 설정하고 프로그램을 실행할 수 있습니다.인터럽트가 발생하여 LLDB에 넣으면 script
명령을 통해 Python 해석기에 추가할 수 있습니다.(lldb) script
Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
>>>
우선 Python에서 sname
변수를 가져오는 것이 가장 중요합니다. 더 구체적으로 말하면 현재 창고 프레임워크에서 가져오는 것은 다음과 같습니다.>>> sname = lldb.frame.FindVariable('sname')
현재, Python 코드를 상호작용으로 시도할 수 있으며, 편집 컴파일 실행 순환을 단축할 수 있습니다.
Reference
이 문제에 관하여(Python에서 C용 LLDB 사용자 정의 데이터 포맷 프로그램), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/pauljlucas/lldb-custom-data-formatters-in-python-5224텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)