IT박스

LLDB의 배열보기 : Xcode 4.1의 GDB '@'연산자와 동일

itboxs 2020. 10. 28. 07:55
반응형

LLDB의 배열보기 : Xcode 4.1의 GDB '@'연산자와 동일


포인터가 가리키는 요소 배열을보고 싶습니다. GDB에서는 '@'연산자를 사용하여 지정된 길이의 인공 배열로 지적 된 메모리를 다음과 같이 처리하여 수행 할 수 있습니다.

*pointer @ length

length보고 싶은 요소의 수는 어디에 있습니까 ?

위의 구문은 Xcode 4.1과 함께 제공되는 LLDB에서 작동하지 않습니다.

LLDB에서 위의 작업을 수행하는 방법이 있습니까?


실제로 포인터를 배열에 대한 포인터로 캐스팅하는 간단한 방법이 있습니다.

예를 들어를 가지고 있고 int* ptr이를 10 개의 정수 배열로 보려면 다음을 수행 할 수 있습니다.

p *(int(*)[10])ptr

표준 C 기능에만 의존하기 때문에이 방법은 플러그인이나 특수 설정없이 작동합니다. 마찬가지로 GDB 또는 CDB와 같은 다른 디버거에서도 작동하지만 배열 인쇄를위한 특수 구문도 있습니다.


Xcode 8.0의 lldb부터 새로운 내장 parray 명령이 있습니다. 따라서 다음과 같이 말할 수 있습니다.

(lldb) parray <COUNT> <EXPRESSION>

의 결과가 가리키는 메모리를 표현식이 가리키는 유형 EXPRESSIONCOUNT요소 배열 로 인쇄합니다 .

카운트가 현재 프레임에서 사용 가능한 변수에 저장되면 다음을 수행 할 수 있습니다.

(lldb) parray `count_variable` pointer_to_malloced_array

이는 일반적인 lldb 기능입니다. 백틱으로 둘러싸인 lldb의 모든 명령 줄 인수는 정수를 반환하는 식으로 평가되고 명령 실행 전에 정수가 인수로 대체됩니다.


내가 찾은 유일한 방법은 Python 스크립팅 모듈을 사용하는 것입니다.

""" File: parray.py """
import lldb
import shlex

def parray(debugger, command, result, dict):
    args = shlex.split(command)
    va = lldb.frame.FindVariable(args[0])
    for i in range(0, int(args[1])):
        print va.GetChildAtIndex(i, 0, 1)

lldb에서 "parray"명령을 정의하십시오.

(lldb) command script import /path/to/parray.py
(lldb) command script add --function parray.parray parray

이제 "parray variable length "를 사용할 수 있습니다 .

(lldb) parray a 5
(double) *a = 0
(double) [1] = 0
(double) [2] = 1.14468
(double) [3] = 2.28936
(double) [4] = 3.43404

Xcode 4.5.1 (지금 도움이 될 수도 있고 없을 수도 있음)을 사용하면 lldb 콘솔에서이 작업을 수행 할 수 있습니다.

(lldb) type summary add -s "${var[0-63]}" "float *"
(lldb) frame variable pointer
  (float *) pointer = 0x000000010ba92950 [0.0,1.0,2.0,3.0, ... ,63.0]

이 예에서는 '포인터'가 64 개의 부동 소수점 배열이라고 가정합니다. float pointer[64];


Martin R 답변으로 시작하여 다음과 같이 개선했습니다.

  1. 포인터가 단순 변수가 아닌 경우, 예 :

    struct {
      int* at;
      size_t size;
    } a;
    

    그런 다음 "parray a.at 5"가 실패합니다.

    "FindVariable"을 "GetValueForVariablePath"로 대체하여이 문제를 해결했습니다.

  2. 이제 배열의 요소가 집계이면 어떻게됩니까?

    struct {
      struct { float x; float y; }* at;
      size_t size;
    } a;
    

    그런 다음 "parray a.at 5"는 다음을 인쇄합니다. a.at-> x, a.at-> y, a.at [2], a.at [3], a.at [4] GetChildAtIndex ()가 멤버를 반환하기 때문입니다. 집계의.

    "a.at"를 확인한 다음 그 자식을 검색하는 대신 루프 내부에서 "a.at"+ "["+ str (i) + "]"를 해결하여이 문제를 해결했습니다.

  3. 선택적인 "첫 번째"인수 (사용 : parray [FIRST] COUNT)를 추가했습니다. 이는 많은 수의 요소가있을 때 유용합니다.

  4. init에서 "command script add -f parray.parray parray"를 수행했습니다.

다음은 수정 된 버전입니다.

import lldb
import shlex

def parray(debugger, command, result, dict):
  args = shlex.split(command)
  if len(args) == 2:
    count = int(args[1])
    indices = range(count)
  elif len(args) == 3:
    first = int(args[1]), count = int(args[2])
    indices = range(first, first + count)
  else:
    print 'Usage: parray ARRAY [FIRST] COUNT'
    return
  for i in indices:
    print lldb.frame.GetValueForVariablePath(args[0] + "[" + str(i) + "]")

def __lldb_init_module(debugger, internal_dict):
  debugger.HandleCommand('command script add -f parray.parray parray')

아직 지원되지 않는 것 같습니다.

메모리 읽기 기능 (메모리 읽기 / x)을 사용할 수 있습니다.

(lldb) memory read -ff -c10 `test`

그 포인터에서 float를 10 번 인쇄합니다. 이것은 gdb의 @과 동일한 기능이어야합니다.


I tried to add a comment but that wasn't great for posting a full answer so I made my own answer. This solves the problem with getting "No Value". You need to get the current frame as I believe lldb.frame is set at module import time so it doesn't have the current frame when you stop at a breakpoint if you load the module from .lldbinit. The other version would work if you import or reloaded the script when you stopped at the breakpoint. The version below should always work.

import lldb
import shlex

@lldb.command('parray', 'command script add -f parray.parray parray')
def parray(debugger, command, result, dict):

    target = debugger.GetSelectedTarget()
    process = target.GetProcess()
    thread = process.GetSelectedThread()
    frame = thread.GetSelectedFrame()

    args = shlex.split(command)
    if len(args) == 2:
        count = int(args[1])
        indices = range(count)
    elif len(args) == 3:
        first = int(args[1])
        count = int(args[2])
        indices = range(first, first + count)
    else:
        print 'Usage: parray ARRAY [FIRST] COUNT'
        return

    for i in indices:
        print frame.GetValueForVariablePath(args[0] + "[" + str(i) + "]")

Well at that point, you may as well write your own custom C function and invoke it with:

call (int)myprint(args)

To inspect variables you can use the frame variable command (fr v is the shortest unique prefix) which has a -Z flag which does exactly what you want:

(lldb) fr v buffer -Z5
(int64_t *) buffer = 0x000000010950c000 {
  (int64_t) [0] = 0
  (int64_t) [1] = 0
  (int64_t) [2] = 0
  (int64_t) [3] = 0
  (int64_t) [4] = 0
}

unfortunately expression does not support that flag

참고URL : https://stackoverflow.com/questions/7062173/view-array-in-lldb-equivalent-of-gdbs-operator-in-xcode-4-1

반응형