2016-04-10 30 views
0

我想要一个格式化程序为buildin字符串类型的nim语言,但不知何故我无法提供它。稔compilis到c,和字符串类型的C表现你在这里看到:为一个大小的字符串类型声明一个lldb汇总字符串

#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) 
# define SEQ_DECL_SIZE /* empty is correct! */ 
#else 
# define SEQ_DECL_SIZE 1000000 
#endif 
typedef char NIM_CHAR; 
typedef long long int NI64; 
typedef NI64 NI; 
struct TGenericSeq {NI len; NI reserved; }; 
struct NimStringDesc {TGenericSeq Sup; NIM_CHAR data[SEQ_DECL_SIZE]; }; 

,这里是什么,我在LLDB会议试图输出:

(lldb) frame variable *longstring 
(NimStringDesc) *longstring = { 
    Sup = (len = 9, reserved = 15) 
    data = {} 
} 
(lldb) frame variable longstring->data 
(NIM_CHAR []) longstring->data = {} 
(lldb) type summary add --summary-string "${&var[0]%s}" "NIM_CHAR []" 
(lldb) frame variable longstring->data 
(NIM_CHAR []) longstring->data = {} 
(lldb) type summary add --summary-string "${var%s}" "NIM_CHAR *" 
(lldb) frame variable longstring->data 
(NIM_CHAR []) longstring->data = {} 
(lldb) frame variable &longstring->data[0] 
(NIM_CHAR *) &[0] = 0x00007ffff7f3a060 "9 - 3 - 2" 
(lldb) frame variable *longstring 
(lldb) type summary add --summary-string "${var.data%s}" "NimStringDesc" 
(lldb) frame variable *longstring 
(NimStringDesc) *longstring = NIM_CHAR [] @ 0x7ffff7f3a060 
(lldb) type summary add --summary-string "${&var.data[0]%s}" "NimStringDesc" 
(lldb) frame variable *longstring 
(NimStringDesc) *longstring = { 
    Sup = (len = 9, reserved = 15) 
    data = {} 
} 
(lldb) 

我根本就”牛逼管理,输出将只是数据解释为'\0'结尾的C字符串

回答

1

你试过摘要字符串形式(设计),没有语法富有C.

由于您使用的是零大小的数组,因此我不认为我们有任何魔术条款将其视为指针字符串。你可能想提出一个关于它的错误,但在这种情况下,它是否会对你有所帮助是有争议的。既然你的字符串是长度编码的,它并不需要以零终止,这是唯一的提示LLDB可以理解开箱即可知道何时停止读出指向字符的指针。

在你的情况,你将不得不求助于Python的格式化

你需要的东西是:

  • 字符串缓冲区的内存位置
  • 字符串的长度缓冲
  • 一个过程来读取存储器出

这是一个非常小的Python SNI PPET是它 - 我给你增强建议为好,但让我们从基础开始:

def NimStringSummary(valobj,stuff): 
    l = valobj.GetChildMemberWithName('Sup').GetChildMemberWithName('len').GetValueAsUnsigned(0) 
    s = valobj.GetChildMemberWithName('data').AddressOf() 
    return '"%s"'% valobj.process.ReadMemory(s.GetValueAsUnsigned(0),l,lldb.SBError()) 

正如你所看到的,首先它读取长度字段的值;然后它读取数据缓冲区的地址;那么它使用值来自读取字符串内容的过程,并将其返回为引号

现在,这是一个概念验证。如果你在生产中使用它,你会很快遇到几个问题:

如果你的字符串缓冲区尚未初始化,它说缓冲区的大小是20千兆字节?你将不得不限制你愿意阅读的数据的大小。对于类字符串类型,它具有(char *,std :: string,Swift.String,...)的内建知识,LLDB输出截断的缓冲区,然后输出...,例如。

(const char*) buffer = "myBufferIsVeryLong"... 

如果指向数据的指针无效怎么办?你应该检查s.GetValueAsUnsigned(0)实际上不是零 - 如果是你可能想打印一个错误信息,比如“null buffer”。

而且,在这里,我只是通过了一项SBError,我则忽略 - 这将是更好地传递一个,然后检查其 总而言之,你最终的东西,如:

import lldb 
import os 

def NimStringSummary(valobj,stuff): 
    l = valobj.GetChildMemberWithName('Sup').GetChildMemberWithName('len').GetValueAsUnsigned(0) 
    if l == 0: return '""' 
    if l > 1024: l = 1024 
    s = valobj.GetChildMemberWithName('data').AddressOf() 
    addr = s.GetValueAsUnsigned(0) 
    if addr == 0: return '<null buffer>' 
    err = lldb.SBError() 
    buf = valobj.process.ReadMemory(s.GetValueAsUnsigned(0),l,err) 
    if err.Fail(): return '<error: %s>' % str(err) 
    return '"%s"' % buf 

def __lldb_init_module(debugger, internal_dict): 
    debugger.HandleCommand("type summary add NimStringDesc -F %s.NimStringSummary" % os.path.splitext(os.path.basename(__file__))[0]) 

的一个额外的窍门是__lldb_init_module函数 - 只要你'命令脚本导入'一个python文件,这个函数就会被LLDB自动调用。这将允许您将'命令脚本导入'添加到您的〜/ .lldbinit文件中,并自动让格式化程序在所有调试会话中被拾取。

希望这有助于!

+1

感谢您的回答,这真的帮了我很多。我会尽快尝试一下。但是在你已经访问了Sup成员之后,你正在检查'data'的地址是否为'0'。数据的地址永远不会是'0',因为字符串是在Sup之后直接嵌入的,它不是一个指针。 – Arne

+0

听起来像一个公平点。那么,随意调整。 –

+0

我保持原样,因为这是我在Stackoverflow上得到的最好的答案,非常感谢。一切正常,而且很好解释。 – Arne

相关问题