python-gdb-mi

GDB's Machine Interface Parser

View on GitHub

Workarounds for GDB MI’s issues

Workaround for inaccuracy while adding a multiple location breakpoint bug.

This bug makes an incorrect output when multiple breakpoints are in the same location: each breakpoint’s data is glued together in a non-conforming MI syntax.

This issue affects the result (synchronous), the asynchronous records and it even affects the results of a Breakpoint Table

=breakpoint-modified,bkpt={...
^done,bkpt={...
BreakpointTable={...

The proposed solution is to replace that by a simple list.

Notice how we also changed the expected keyword bkpt by bkpts:

>>> text = '=breakpoint-modified,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="<MULTIPLE>",times="1",original-location="roll"},{number="1.1",enabled="y",addr="0x08048563",func="roll",file="two_pthreads.c",fullname="/threads/two_pthreads.c",line="5",thread-groups=["i1"]},{number="1.2",enabled="y",addr="0x08048563",func="roll",file="two_pthreads.c",fullname="/threads/two_pthreads.c",line="5",thread-groups=["i2"]}\n'

>>> import pprint
>>> from gdb_mi import Output

>>> o = Output()

>>> record = o.parse_line(text)
>>> record.async_class, record.type
('breakpoints-modified', 'Notify')

>>> record
{'bkpts': [{'addr': '<MULTIPLE>',
            'disp': 'keep',
            'enabled': 'y',
            'number': '1',
            'original-location': 'roll',
            'times': '1',
            'type': 'breakpoint'},
           {'addr': '0x08048563',
            'enabled': 'y',
            'file': 'two_pthreads.c',
            'fullname': '/threads/two_pthreads.c',
            'func': 'roll',
            'line': '5',
            'number': '1.1',
            'thread-groups': ['i1']},
           {'addr': '0x08048563',
            'enabled': 'y',
            'file': 'two_pthreads.c',
            'fullname': '/threads/two_pthreads.c',
            'func': 'roll',
            'line': '5',
            'number': '1.2',
            'thread-groups': ['i2']}],
 'class': 'breakpoints-modified',
 'token': None,
 'type': 'Notify'}

To make this behavior uniform we apply the same change even if there is only one breakpoint:

>>> 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'
>>> record = o.parse_line(text)
>>> record.result_class, record.type
('done', 'Result')

>>> record
{'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'}],
 'class': 'done',
 'token': None,
 'type': 'Result'}

Due the same bug, we need to modify the event BreakpointTable which lists the breakpoints and if some of them are in the same address, this will trigger the same bug.

Here is the fix:

>>> text = '^done,BreakpointTable={nr_rows="3",nr_cols="6",hdr=[{width="7",alignment="-1",col_name="number",colhdr="Num"},{width="14",alignment="-1",col_name="type",colhdr="Type"},{width="4",alignment="-1",col_name="disp",colhdr="Disp"},{width="3",alignment="-1",col_name="enabled",colhdr="Enb"},{width="18",alignment="-1",col_name="addr",colhdr="Address"},{width="40",alignment="2",col_name="what",colhdr="What"}],body=[bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="<MULTIPLE>",times="0",original-location="roll"},{number="1.1",enabled="y",addr="0x00000000004006a9",func="roll",file="three_pthreads.c",fullname="/threads/three_pthreads.c",line="5",thread-groups=["i1"]},{number="1.2",enabled="y",addr="0x00000000004006a9",func="roll",file="three_pthreads.c",fullname="/threads/three_pthreads.c",line="5",thread-groups=["i2"]},bkpt={number="2",type="breakpoint",disp="keep",enabled="y",addr="<MULTIPLE>",times="0",original-location="roll"},{number="2.1",enabled="y",addr="0x00000000004006a9",func="roll",file="three_pthreads.c",fullname="/threads/three_pthreads.c",line="5",thread-groups=["i1"]},{number="2.2",enabled="y",addr="0x00000000004006a9",func="roll",file="three_pthreads.c",fullname="/threads/three_pthreads.c",line="5",thread-groups=["i2"]},bkpt={number="3",type="breakpoint",disp="keep",enabled="y",addr="<MULTIPLE>",times="0",original-location="roll"},{number="3.1",enabled="y",addr="0x00000000004006a9",func="roll",file="three_pthreads.c",fullname="/threads/three_pthreads.c",line="5",thread-groups=["i1"]},{number="3.2",enabled="y",addr="0x00000000004006a9",func="roll",file="three_pthreads.c",fullname="/threads/three_pthreads.c",line="5",thread-groups=["i2"]}]}\n'

>>> record = o.parse_line(text)
>>> record              # byexample: -tags
{'BreakpointTable': {'body': [{'addr': '<MULTIPLE>',
                               'disp': 'keep',
                               'enabled': 'y',
                               'number': '1',
                               'original-location': 'roll',
                               'times': '0',
                               'type': 'breakpoint'},
                              {'addr': '0x00000000004006a9',
                               'enabled': 'y',
                               'file': 'three_pthreads.c',
                               'fullname': '/threads/three_pthreads.c',
                               'func': 'roll',
                               'line': '5',
                               'number': '1.1',
                               'thread-groups': ['i1']},
                              {'addr': '0x00000000004006a9',
                               'enabled': 'y',
                               'file': 'three_pthreads.c',
                               'fullname': '/threads/three_pthreads.c',
                               'func': 'roll',
                               'line': '5',
                               'number': '1.2',
                               'thread-groups': ['i2']},
                              {'addr': '<MULTIPLE>',
                               'disp': 'keep',
                               'enabled': 'y',
                               'number': '2',
                               'original-location': 'roll',
                               'times': '0',
                               'type': 'breakpoint'},
                              {'addr': '0x00000000004006a9',
                               'enabled': 'y',
                               'file': 'three_pthreads.c',
                               'fullname': '/threads/three_pthreads.c',
                               'func': 'roll',
                               'line': '5',
                               'number': '2.1',
                               'thread-groups': ['i1']},
                              {'addr': '0x00000000004006a9',
                               'enabled': 'y',
                               'file': 'three_pthreads.c',
                               'fullname': '/threads/three_pthreads.c',
                               'func': 'roll',
                               'line': '5',
                               'number': '2.2',
                               'thread-groups': ['i2']},
                              {'addr': '<MULTIPLE>',
                               'disp': 'keep',
                               'enabled': 'y',
                               'number': '3',
                               'original-location': 'roll',
                               'times': '0',
                               'type': 'breakpoint'},
                              {'addr': '0x00000000004006a9',
                               'enabled': 'y',
                               'file': 'three_pthreads.c',
                               'fullname': '/threads/three_pthreads.c',
                               'func': 'roll',
                               'line': '5',
                               'number': '3.1',
                               'thread-groups': ['i1']},
                              {'addr': '0x00000000004006a9',
                               'enabled': 'y',
                               'file': 'three_pthreads.c',
                               'fullname': '/threads/three_pthreads.c',
                               'func': 'roll',
                               'line': '5',
                               'number': '3.2',
                               'thread-groups': ['i2']}],
                     'hdr': [{'alignment': '-1',
                              'col_name': 'number',
                              'colhdr': 'Num',
                              'width': '7'},
                             {'alignment': '-1',
                              'col_name': 'type',
                              'colhdr': 'Type',
                              'width': '14'},
                             {'alignment': '-1',
                              'col_name': 'disp',
                              'colhdr': 'Disp',
                              'width': '4'},
                             {'alignment': '-1',
                              'col_name': 'enabled',
                              'colhdr': 'Enb',
                              'width': '3'},
                             {'alignment': '-1',
                              'col_name': 'addr',
                              'colhdr': 'Address',
                              'width': '18'},
                             {'alignment': '2',
                              'col_name': 'what',
                              'colhdr': 'What',
                              'width': '40'}],
                     'nr_cols': '6',
                     'nr_rows': '3'},
 'class': 'done',
 'token': None,
 'type': 'Result'}