2

UIVIews に関連する可能性のある問題をデバッグする一環として、LLDB から実行する Python スクリプトを作成したいと考えています。状態を比較できるように、ブレークポイント内のビューとすべてのビューの子のすべての設定を抽出することを考えていました。このトピックに関する WWDC ビデオをチェックしてから、時間をかけて lldb.llvm.org/scripting.html を読みましたが、あまり役に立ちませんでした。例をウェブで検索しても、それらと実質的に異なるものは何も見つかりませんでした。

私の問題は、ブレークポイントで iOS 変数にアクセスする方法を見つけようとしていることです。私が見た例では、数値の変換やシェル コマンドの模倣などを行っています。興味深いものですが、私の目的には役に立ちません。「スクリプトのヘルプ(lldb.SBValue)」などでヘルプ情報を読んでいるのですが、結果が膨大で使用パターンが不明なため、処理が遅いです。いくつかの iOS オブジェクトをトラバースする方法の 1 つの適切な例は、システムを理解するのに役立つと思います。誰かが知っているか、コードのスニペットを共有できますか?

アップデート:

これを書いたのは、UIView の使用におけるバグを追跡するのに役立つためです。ビューツリー全体を表示できるかどうかを確認するために、これを改良するためにもう少し作業を行いたいのですが、これで問題を解決するのに十分だったので、他の人の時間を節約するためにここに置きます.

import lldb
max_depth = 6
filters = {'_view':'UIView *', '_layer':'CALayer *', '_viewFlags':'struct'}

def print_value(var, depth, prefix):
    """ print values and recurse """
    global max_depth
    local_depth = max_depth - depth
    pad = ' ' * local_depth
    name = var.GetName()
    typ = str(var.GetType()).split('\n')[0].split('{')[0].split(':')[0].strip()

    found = name in filters.keys() # only visit filter items children
    if found:
        found = (filters.get(name) == typ)

    value = var.GetValue()
    if value is None or str(value) == '0x00000000':
        value = ''
    else:
        value = ' Val: %s' % value

    if var.GetNumChildren() == 0 and var.IsInScope():
        path = lldb.SBStream()
        var.GetExpressionPath(path)
        path = ' pathData: %s' % path.GetData()
    else:
        path = ''

    print '^' * local_depth, prefix, ' Adr:', var.GetAddress(), ' Name:', name, ' Type:', typ, value, path

    if var.GetNumChildren() > 0:
        if local_depth < 2 or found:
            print pad, var.GetNumChildren(), 'children, to depth', local_depth + 1
            counter = 0
            for subvar in var:
                subprefix = '%d/%d' % (counter, var.GetNumChildren())
                print_value(subvar, depth - 1, subprefix)
                counter += 1

def printvh (debugger, command_line, result, dict):
    """ print view hierarchy """
    global max_depth
    args = command_line.split()
    if len(args) > 0:
        var = lldb.frame.FindVariable(args[0])
        depth = max_depth
        if len(args) > 1:
            depth = int(args[1])
            max_depth = depth
        print_value(var, depth, 'ROOT')
    else:
        print 'pass a variable name and optional depth'

そして、以下を .lldbinit に追加しました:

script import os, sys
# So that files in my dir takes precedence.
script sys.path[:0] = [os.path.expanduser("~/lldbpy")]
script import views
command script add -f views.printvh printvh

LLDB プロンプトで「printvh self 3」と入力するだけです。

4

2 に答える 2

6

多分これは役立つでしょう。ブレークポイントに到達したときに単純なローカル変数をダンプする方法の例を次に示します。char *配列を正しく表示していません。これらのデータを取得して、「フレーム変数」が表示するように表示する方法がわかりませんが、後で空き時間があるときにわかります。

struct datastore {
  int val1;
  int val2;
  struct {
     int val3;
  } subdata;
  char *name;
};

int main (int argc, char **argv)
{
  struct datastore data = {1, 5, {3}, "a string"};
  return data.val2;
}

Current executable set to 'a.out' (x86_64).
(lldb) br se -l 13
Breakpoint created: 1: file ='a.c', line = 13, locations = 1
(lldb) br comm add -s python
Enter your Python command(s). Type 'DONE' to end.
> def printvar_or_children(var):
>   if var.GetNumChildren() == 0 and var.IsInScope():
>     path = lldb.SBStream()
>     var.GetExpressionPath(path)
>     print '%s: %s' % (path.GetData(), var.GetValue())
>   else: 
>     for subvar in var:
>       printvar_or_children(subvar)
> 
> print 'variables visible at breakpoint %s' % bp_loc
> for var in frame.arguments:
>   printvar_or_children(var)
> for var in frame.locals:
>   printvar_or_children(var)
> 
> DONE
(lldb) r
variables visible at breakpoint 1.1: where = a.out`main + 51 at a.c:13, address = 0x0000000100000f33, resolved, hit count = 1 
argc: 1
*(*(argv)): '/'
data.val1: 1
data.val2: 5
data.subdata.val3: 3
*(data.name): 'a'
Process 84865 stopped
* thread #1: tid = 0x1f03, 0x0000000100000f33 a.out`main + 51 at a.c:13, stop reason = breakpoint 1.1
    frame #0: 0x0000000100000f33 a.out`main + 51 at a.c:13
   10   int main (int argc, char **argv)
   11   {
   12     struct datastore data = {1, 5, {3}, "a string"};
-> 13     return data.val2;
(lldb)

ヒント-正気のために、サイドテキストエディターでPythonを操作し、実験しながらlldbに貼り付けました。

lldbでframevariableコマンドを使用して、特定の停止位置で変数を探索する場合、これは、「frame」オブジェクトのブレークポイントpythonコマンドに提供されるSBFrameを介して変数にアクセスできるのと同じ基本的な方法です。

それがあなたが始めるのに役立つことを願っています。

于 2012-10-01T09:11:20.187 に答える
2

次の場所に保存されている python LLDB フォーマット テンプレートを調べてみましたか。

XCode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python/lldb/formatters/objc
于 2012-10-01T07:15:43.767 に答える