rfj at google dot com
2018-07-03 21:01:42 UTC
https://sourceware.org/bugzilla/show_bug.cgi?id=23367
Bug ID: 23367
Summary: MI emits error about "Duplicate variable object name"
if pretty-printer prepends to children on subsequent
enumerations
Product: gdb
Version: HEAD
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: mi
Assignee: unassigned at sourceware dot org
Reporter: rfj at google dot com
Target Milestone: ---
Release: GNU gdb (Debian 7.12-6) 7.12.0.20161007-git, GNU gdb (GDB)
8.1.50.20180618-git
Environment: Linux 4.5.18-x86, gcc 7.3.0, This GDB was configured as
"i686-linux-gnu".
This still manifests as of git commit d7e15655a40e9133a1cbf53ea071f82cd6745ac8
(current master HEAD).
The proglem occurs if a pretty-printer return a list of children similar to:
[('a', 1), ('b', 2), ('c', 3)]
and then later returns a list for the same var with an element prepended:
[('problem', 0xbad), ('a', 1), ('b', 2), ('c', 3)]
It seems like install_dynamic_child() in varobj.c will iterate over the
elements by index, notice that index 3 is beyond the previous length, and try
to add a child with the name 'c'. This will fail because 'c' already exist in
the varobj children VEC.
A small repro of the problem (3 files: "foo_test.cc", "foo_test-gdb.py", and
"mi_commands.txt"):
foo_test.cc:
struct foo { int a; };
int main(int argc, char *argv[]) {
foo fs[] = {
{0},
{1},
};
for (const foo &f: fs) {
if (f.a == 255) {
return 1;
}
}
return 0;
}
foo_test-gdb.py:
import gdb
class fooPrinter:
"""Print a foo object."""
def __init__(self, val):
self.val = val
def children(self):
if self.val['a'] == 1:
return [('problem', 0xbad), ('a', self.val['a'])]
return [('a', self.val['a']),]
def to_string(self):
return ('a=<' + str(self.val['a']) +'>')
def build_pretty_printer():
pp = gdb.printing.RegexpCollectionPrettyPrinter('my_library')
pp.add_printer('foo', '^foo$', fooPrinter)
return pp
if __name__ == '__main__':
gdb.printing.register_pretty_printer(
gdb.current_objfile(),
build_pretty_printer())
mi_commands.txt:
-enable-pretty-printing
-break-insert -f "foo_test.cc:9"
-exec-run
-var-create "f" * "f"
-var-list-children --all-values "f" -1 -1
-exec-continue
-var-update --all-values *
Build and run:
g++ -ggdb foo_test.cc -o foo_test
gdb -iex 'set auto-load safe-path .' --interpreter=mi2 ./foo_test <
mi_commands.txt
Towards the end of the output should be something similar to:
^error,msg="Duplicate variable object name"
Bug ID: 23367
Summary: MI emits error about "Duplicate variable object name"
if pretty-printer prepends to children on subsequent
enumerations
Product: gdb
Version: HEAD
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: mi
Assignee: unassigned at sourceware dot org
Reporter: rfj at google dot com
Target Milestone: ---
Release: GNU gdb (Debian 7.12-6) 7.12.0.20161007-git, GNU gdb (GDB)
8.1.50.20180618-git
Environment: Linux 4.5.18-x86, gcc 7.3.0, This GDB was configured as
"i686-linux-gnu".
This still manifests as of git commit d7e15655a40e9133a1cbf53ea071f82cd6745ac8
(current master HEAD).
The proglem occurs if a pretty-printer return a list of children similar to:
[('a', 1), ('b', 2), ('c', 3)]
and then later returns a list for the same var with an element prepended:
[('problem', 0xbad), ('a', 1), ('b', 2), ('c', 3)]
It seems like install_dynamic_child() in varobj.c will iterate over the
elements by index, notice that index 3 is beyond the previous length, and try
to add a child with the name 'c'. This will fail because 'c' already exist in
the varobj children VEC.
A small repro of the problem (3 files: "foo_test.cc", "foo_test-gdb.py", and
"mi_commands.txt"):
foo_test.cc:
struct foo { int a; };
int main(int argc, char *argv[]) {
foo fs[] = {
{0},
{1},
};
for (const foo &f: fs) {
if (f.a == 255) {
return 1;
}
}
return 0;
}
foo_test-gdb.py:
import gdb
class fooPrinter:
"""Print a foo object."""
def __init__(self, val):
self.val = val
def children(self):
if self.val['a'] == 1:
return [('problem', 0xbad), ('a', self.val['a'])]
return [('a', self.val['a']),]
def to_string(self):
return ('a=<' + str(self.val['a']) +'>')
def build_pretty_printer():
pp = gdb.printing.RegexpCollectionPrettyPrinter('my_library')
pp.add_printer('foo', '^foo$', fooPrinter)
return pp
if __name__ == '__main__':
gdb.printing.register_pretty_printer(
gdb.current_objfile(),
build_pretty_printer())
mi_commands.txt:
-enable-pretty-printing
-break-insert -f "foo_test.cc:9"
-exec-run
-var-create "f" * "f"
-var-list-children --all-values "f" -1 -1
-exec-continue
-var-update --all-values *
Build and run:
g++ -ggdb foo_test.cc -o foo_test
gdb -iex 'set auto-load safe-path .' --interpreter=mi2 ./foo_test <
mi_commands.txt
Towards the end of the output should be something similar to:
^error,msg="Duplicate variable object name"
--
You are receiving this mail because:
You are on the CC list for the bug.
You are receiving this mail because:
You are on the CC list for the bug.