ポインターが指す要素の配列を表示したいと思います。 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>
EXPRESSION
の結果が指すメモリを、式が指す型のCOUNT
要素の配列として出力します。
現在のフレームで使用可能な変数にカウントが保存されている場合、次のことができることを忘れないでください。
(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 可変長」を使用できます。
(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の配列であると想定しています。float pointer[64];
Martin Rの回答から始めて、次のように改善しました。
ポインターが単純な変数ではない場合、例えば:
struct {
int* at;
size_t size;
} a;
次に、「parray a.at 5」が失敗します。
「FindVariable」を「GetValueForVariablePath」に置き換えることでこれを修正しました。
配列内の要素が集合体である場合、たとえば:
struct {
struct { float x; float y; }* at;
size_t size;
} a;
次に、「parray a.at 5」が出力されます。GetChildAtIndex()がメンバーを返すため、a.at-> x、a.at-> y、a.at [2]、a.at [3]、a.at [4]が出力されます。集合体の。
「a.at」を解決してからその子を取得するのではなく、ループ内で「a.at」+「[」+ str(i)+「]」を解決することでこれを修正しました。
オプションの「最初の」引数(使用法:parray [FIRST] COUNT)が追加されました。これは、膨大な数の要素がある場合に役立ちます。
Initで「コマンドスクリプト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`
そのポインターからフロートを10回印刷します。これは、gdbの@と同じ機能でなければなりません。
コメントを追加しようとしましたが、完全な回答を投稿するのには向いていなかったので、自分で回答しました。これにより、「値なし」を取得することで問題が解決します。 lldb.frameはモジュールのインポート時に設定されるため、.lldbinitからモジュールをロードする場合、ブレークポイントで停止したときに現在のフレームが存在しないと思われるため、現在のフレームを取得する必要があります。ブレークポイントで停止したときにスクリプトをインポートまたは再ロードすると、他のバージョンが機能します。以下のバージョンは常に動作するはずです。
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) + "]")
その時点で、独自のカスタムC関数を作成し、次のコマンドで呼び出すこともできます。
call (int)myprint(args)
変数を検査するには、frame variable
コマンド(fr v
は最短の一意のプレフィックスです)-Z
必要なことを正確に行うフラグ:
(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
}
残念ながらexpression
はそのフラグをサポートしていません