gdb机器接口(mi)事件的分析器。
python-gdb-mi的Python项目详细描述
python gdb mi解析器
MI或 机器接口是与gdb、gnu交互的新接口。 调试器,来自另一个程序。
gdb机器接口的输出是面向行的,基于文本的。它 是从字符串到字典的小元素的组合
python-gdb-mi是用于python 2.x/3.x的简单而健壮的解析器 可以将这些行转换为python对象 如果需要json,则序列化。
概述
GDB MI文本可以如下:
>>>text='^done,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x08048564",func="main",file="myprog.c",fullname="/home/nickrob/myprog.c",line="68",thread-groups=["i1"],times="0"}\n'
当断点是 集合。
要解析它,我们需要使用 parse_line方法:
>>>fromgdb_miimportOutput>>>out=Output()>>>record=out.parse_line(text)>>>record#doctest: +NORMALIZE_WHITESPACE{'klass':'done','results':{'bkpts':[{'addr':'0x08048564','disp':'keep','enabled':'y','file':'myprog.c','fullname':'/home/nickrob/myprog.c','func':'main','line':'68','number':'1','thread-groups':['i1'],'times':'0','type':'breakpoint'}]},'token':None,'type':'Sync'}
如果gdb的输出不是一个完整的行,Output可以处理它 无论如何做些缓冲。使用parse而不是parse_line来 馈送Output:
>>>out.parse(text[:10])# incomplete line, None returned>>>out.parse(text[10:])# enough data, parse it! doctest: +NORMALIZE_WHITESPACE{'klass':'done','results':{'bkpts':[{'addr':'0x08048564','disp':'keep','enabled':'y','file':'myprog.c','fullname':'/home/nickrob/myprog.c','func':'main','line':'68','number':'1','thread-groups':['i1'],'times':'0','type':'breakpoint'}]},'token':None,'type':'Sync'}
分析结果
parse_line和parse可以返回三种类型的对象:
- Stream表示output record 来自:控制台、目标和日志。
- Record表示或同步的result record 或者是带外的asynchronous record, 用于通知已发生的更改。
- (gdb)表示空提示行的文本字符串。
Stream和Record都有一个要转换的as_native方法 它们构成了python的指令和列表。
流
>>>fromgdb_miimportStream>>>text='~"GDB rocks!"\n'>>>stream=out.parse_line(text)>>>stream# same as pprint.pprint(stream.as_native()){'stream':'GDB rocks!','type':'Console'}>>>isinstance(stream,Stream)True
type属性是one of the following, 从gdb mi的文档中:-Console:输出应该是 在控制台中显示。它是对cli的文本响应 命令。-Target:目标程序生成的输出。-Log: 来自gdb内部的输出文本,例如 应显示为错误日志的一部分。
记录
我们已经看到了一个Record的例子,在这种情况下,它是 同步result record:
>>>fromgdb_miimportRecord>>>isinstance(record,Record)True>>>record.klass,record.type('done','Sync')
klass属性是one of the following: done,running,connected,error或exit。
对于synchronous result record,属性是Sync。
下面是一个asynchronous record:
>>>text='42*stopped,reason="breakpoint-hit",disp="keep",bkptno="1",thread-id="0",frame={addr="0x08048564",func="main",args=[{name="argc",value="1"},{name="argv",value="0xbfc4d4d4"}],file="myprog.c",fullname="/home/nickrob/myprog.c",line="68"}\n'>>>record=out.parse_line(text)>>>record#doctest: +NORMALIZE_WHITESPACE{'klass':'stopped','results':{'bkptno':'1','disp':'keep','frame':{'addr':'0x08048564','args':[{'name':'argc','value':'1'},{'name':'argv','value':'0xbfc4d4d4'}],'file':'myprog.c','fullname':'/home/nickrob/myprog.c','func':'main','line':'68'},'reason':'breakpoint-hit','thread-id':'0'},'token':42,'type':'Exec'}>>>isinstance(record,Record)True>>>record.klass,record.type('stopped','Exec')
对于asynchronous record,属性type是one of the following 对于AsyncRecords:Exec,Status或Notify。
>;来自gdb mi的文档:-Exec:异步状态更改 在目标上(停止,开始,消失)。-Status:正在进行 有关慢速操作进度的状态信息。可能是 丢弃的。-Notify:客户机的补充信息 应该处理(例如,一个新的断点信息)。
同步和异步两种记录都有两个额外的 属性:-token:由gdb用于匹配请求和 回应。-results:消息中包含的数据将 取决于gdb消息。
来自目标的干扰
如果不重定向目标的输出或将其发送到新控制台 运行gdbset new-console on命令,目标的输出 会干扰解析器。
不幸的是我们无能为力。即使我们忽略了 无法确定何时可以安全丢弃邮件。
例如,以下C代码生成不明确的输出:
printf("~looks like a GDB stream but it isn't\n");
即使你认为这是不可能的,这里有一个相当常见的问题:
printf("normal output 42");/* no newline at the end */fflush(stdout);/* but we flush to the console anyway */
现在假设gdb在fflush指令之后到达一个断点, 我们将看到:
>>>text='normal output 4242*stopped,reason="breakpoint-hit",<and so on...>\n'
问题是所有这些弦都粘在一起,这会导致 为了讨厌的错误。我们可以尝试使用一些regexp,但它也会 易碎品(是token42还是4242?).
相反,如果您试图解析类似的内容,我们会尝试发出警告:
>>>out.parse_line(text)#doctest: +IGNORE_EXCEPTION_DETAILTraceback(mostrecentcalllast):ParsingError:Invalidinput.Maybethetarget's output is interfering with the GDB MI'smessages.Trytoredirectthetarget's output to elsewhere or run GDB's'set new-console on'command.Foundat0position.Originalmessage:normaloutput4242*stopped,reason="breakpoint-hit",<andsoon...>
黑客攻击/贡献
去吧!克隆存储库,执行一个小的修复/增强,运行 make test以确保一切正常工作,然后 提出你的请求!