Bug 23367 - MI emits error about "Duplicate variable object name" if pretty-printer prepends to children on subsequent enumerations
Summary: MI emits error about "Duplicate variable object name" if pretty-printer prepe...
Status: UNCONFIRMED
Alias: None
Product: gdb
Classification: Unclassified
Component: varobj (show other bugs)
Version: HEAD
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 18582 (view as bug list)
Depends on:
Blocks:
 
Reported: 2018-07-03 21:01 UTC by Rohan Joyce
Modified: 2024-01-13 18:33 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Rohan Joyce 2018-07-03 21:01:42 UTC
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"
Comment 1 Tom Tromey 2022-05-25 18:49:03 UTC
*** Bug 18582 has been marked as a duplicate of this bug. ***
Comment 2 Tom Tromey 2023-08-31 17:17:22 UTC
I guess I don't understand why gdb doesn't just fully
synthesize all the names.  But maybe this goes along
with "pretty printing v2", since we may need to split
the name / access fields.
Comment 3 Hannes Domani 2024-01-13 18:33:00 UTC
Seems related to PR18584.