编写 Python 脚本以在 lldb 中打印出一个 recs 数组

Posted

技术标签:

【中文标题】编写 Python 脚本以在 lldb 中打印出一个 recs 数组【英文标题】:Writing a Python script to print out an array of recs in lldb 【发布时间】:2014-03-08 18:13:51 【问题描述】:

我需要有关lldb Python 模块中使用的SBValue class 的帮助,该模块用于为lldb 调试会话创建脚本。

我正在将我的 kext 测试和调试系统从gdb 移植到lldb,这样我就可以开始使用最新版本的XcodeMac OS 10.9.1。这个过程的一部分是在 python 中重写我的 gdb 调试脚本,以便它们可以与 lldb 一起使用。

我有两个 mac 设置工作,可以放入 lldb 并在受害者 Mac 的内核中四处寻找。我还可以在运行 lldb 会话时调用我的 Python 脚本。我被困在我无法弄清楚如何显示记录数组的内容。

例如,给定一个TraceRecs 的数组:

typedef struct


    mach_timespec_t timeStamp;
    thread_t thread;
    TraceRecordType recordType;
    char entry[kEntrySize];
 TraceRec;

一个包含跟踪记录数组的类

class com_softraid_TraceLog

    private:
        UInt32 fMaxNumberEntries;
        UInt32 fNextEntryNumber;
        TraceRec * fTraceRecArray;
        .
        .
        .

内核中的一个全局变量指向这个类的一个对象:

extern com_softraid_TraceLog * com_softraid_gTraceLogPtr;

我可以使用以下 Python 脚本来获取 lldb 中 com_softraid_gTraceLogPtr 的值:

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import lldb
import commands
import optparse
import shlex

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

def srtrace(debugger, user_input, result, internal_dict):
    """srtrace [number_entries]  dump out that number of entries, default = 0 = all entries"""

    target = debugger.GetSelectedTarget()
    traceLog = target.FindFirstGlobalVariable("com_softraid_gTraceLogPtr")
    traceRecordArray = traceLog.GetChildMemberWithName("fTraceRecArray")
    maxNumberEntries = traceLog.GetChildMemberWithName("fMaxNumberEntries").GetValueAsUnsigned()
    nextEntryNumber = traceLog.GetChildMemberWithName("fNextEntryNumber").GetValueAsUnsigned()

    print >>result, "SRLog Current Entry: %d, Log Size: %d" % (nextEntryNumber, maxNumberEntries)

    print >>result, traceRecordArray

输出是:

(lldb) srtrace
SRLog Current Entry: 388, Log Size: 8192
(TraceRec *) fTraceRecArray = 0xffffff80a48fd000

但我不知道如何显示数组中任何记录的字段中的值。我已经尝试了 SBValue 类中的大多数方法,但没有任何运气。

有谁知道这应该如何工作?任何帮助都会很棒。

P。 S.:如果其他人试图让它工作,第一步应该是更新到 Xcode 5.1 b5。 Xcode 5.1 b3 自带的 lldb 版本在显示 IOKit 类的内容子类时经常崩溃。

【问题讨论】:

【参考方案1】:

您正在寻找SBValue::GetChildAtIndex(),但您需要使用该API 的长格式。例如,对于一个独立的用户进程 C 文件,

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef struct

    int datum;
 TraceRec;

typedef struct

        uint32_t fMaxNumberEntries;
        uint32_t fNextEntryNumber;
        TraceRec *fTraceRecArray;
 com_softraid_TraceLog;

com_softraid_TraceLog *com_softraid_gTraceLogPtr;

int main ()

    com_softraid_TraceLog log;
    com_softraid_gTraceLogPtr = &log;
    log.fTraceRecArray = (TraceRec *) malloc (sizeof (TraceRec) * 100);
    log.fMaxNumberEntries = 100;
    log.fNextEntryNumber = 4;
    log.fTraceRecArray[0].datum = 0;
    log.fTraceRecArray[1].datum = 1;
    log.fTraceRecArray[2].datum = 2;
    log.fTraceRecArray[3].datum = 3;

    puts ("break here");

    return 0;

我们可以在交互式脚本模式下进行一些实验:

(lldb) br s -p break
(lldb) r
(lldb) scri
>>> debugger = lldb.debugger
>>> target = debugger.GetSelectedTarget()
>>> traceLog = target.FindFirstGlobalVariable("com_softraid_gTraceLogPtr")
>>> traceRecordArray = traceLog.GetChildMemberWithName("fTraceRecArray")
>>> print traceRecordArray.GetChildAtIndex(1, lldb.eNoDynamicValues, 1)
(TraceRec) [1] = 
  datum = 1

>>> print traceRecordArray.GetChildAtIndex(2, lldb.eNoDynamicValues, 1)
(TraceRec) [2] = 
  datum = 2

>>> 

还有SBValue::GetPointeeData() 可以为您提供SBData 对象中数组每个成员的原始字节,但是您需要将这些字节强制返回到您的结构中,所以我不会那样做。

【讨论】:

当我尝试时,我得到“没有价值”(我准确地输入了你的行)。我可以打印 traceRecordArray 但无法打印 GetChildAtIndex() 的结果 嗯,那是 Xcode 5.0 的 lldb (lldb-300.2.53)。我稍后会仔细检查您使用的 Xcode - 但是这里的示例没有隐藏我的袖子。我想不出你正在使用的 lldb 中的任何东西会导致行为差异......可能还有其他原因导致它不适合你。为了清楚起见——你在我上面写的用户进程测试文件上试过这个,它没有用?还是在 kext 上? 我在kext上用远程调试试过了。两台 Mac 都运行 10.9.1。运行 Xcode 5.1 b5 的开发 Mac。我通过运行 xcrun lldb -s lldb_init 启动 lldb(其中 lldb_init 是我的会话初始化文件)。 lldb版本为:lldb-310.2.34。 看来不是python模块的问题,而是kdp接口的问题。我也无法让 lldb 输出TraceRec。尝试打印 fTraceRecArray 指向的记录导致:(lldb) p *(TraceRec *) com_softraid_gTraceLogPtr-&gt;fTraceRecArray error: incomplete type 'TraceRec' (aka '&lt;anonymous struct&gt;') where a complete type is required note: forward declaration of '&lt;anonymous struct&gt;' error: 1 errors parsing expression 有趣,此时最好在bugreport.apple.com 提交错误报告以进一步调查。如果可能,请包含您的 softraid.kext 和 softraid.kext.dSYM 的副本,并在您无法打印的地方包含image lookup -v -a $pc 的输出,它将准确显示您在 kext 中停止的位置当时。

以上是关于编写 Python 脚本以在 lldb 中打印出一个 recs 数组的主要内容,如果未能解决你的问题,请参考以下文章

使用Python扩展lldb

使用 Xcode/LLDB 打印/调试 libc++ STL

如何让lldb打印写在Objective-C类别中的描述

打印变量时出错 lldb_expr

(lldb) 以十六进制打印 unsigned long long

lldb----打印出类中所有函数的入口地址