Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doxygen annotation in C code incomplete #8

Closed
chiggs opened this issue Jun 18, 2013 · 4 comments
Closed

Doxygen annotation in C code incomplete #8

chiggs opened this issue Jun 18, 2013 · 4 comments
Assignees
Labels
category:docs documentation issues and fixes

Comments

@chiggs
Copy link
Contributor

chiggs commented Jun 18, 2013

Some of the C files need tidying up.

@themperek
Copy link
Contributor

@cmarqu Can this be closed?

@cmarqu
Copy link
Contributor

cmarqu commented Feb 9, 2020

No, there is barely anything documented in Doxygen format in the non-Python files.

@cmarqu cmarqu added the category:docs documentation issues and fixes label Jul 27, 2020
@ktbarrett ktbarrett self-assigned this Dec 18, 2020
@ktbarrett
Copy link
Member

I will complete the documentation of the GPI once all the libraries are merged (#2274).

@ktbarrett
Copy link
Member

We decided to pare down the C documentation to just the GPI (#2274), and that is now down.

imphil added a commit to imphil/cocotb that referenced this issue Oct 12, 2022
cocotb crashes when running the mixed language example with Riviera-PRO,
using a Verilog toplevel and the pre-built binary wheels (manylinux2014,
built on CentOS7).

Valgrind reports

```
 COUT: ==6174== Invalid free() / delete / delete[] / realloc()
 COUT: ==6174==    at 0xC78271B: operator delete(void*) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
 COUT: ==6174==    by 0x1CE1AC80: std::string::assign(std::string const&) (in /home/philipp/src/cocotb-riviera-debug-3078-binary/.direnv/python-3.10.7/lib/python3.10/site-packages/cocotb/libs/libgpilog.so)
 COUT: ==6174==    by 0x1CDE56C6: GpiObjHdl::initialise(std::string const&, std::string const&) (GpiCbHdl.cpp:74)
 COUT: ==6174==    by 0x1CE3D587: VhpiObjHdl::initialise(std::string const&, std::string const&) (VhpiCbHdl.cpp:258)
 COUT: ==6174==    by 0x1CE46932: VhpiImpl::create_gpi_obj_from_handle(unsigned int*, std::string&, std::string&) (VhpiImpl.cpp:462)
 COUT: ==6174==    by 0x1CE470E5: VhpiImpl::native_check_create(std::string&, GpiObjHdl*) (VhpiImpl.cpp:575)
 COUT: ==6174==    by 0x1CDE6E1E: gpi_get_handle_by_name_(GpiObjHdl*, std::string, GpiImplInterface*) (GpiCommon.cpp:297)
 COUT: ==6174==    by 0x1CDE711C: gpi_get_handle_by_name (GpiCommon.cpp:339)
 COUT: ==6174==    by 0x14BF9595: get_handle_by_name((anonymous namespace)::gpi_hdl_Object<GpiObjHdl*>*, _object*) (simulatormodule.cpp:681)
 COUT: ==6174==    by 0x1CF7351A: ??? (in /usr/lib64/libpython3.10.so.1.0)
 COUT: ==6174==    by 0x1CF77976: _PyEval_EvalFrameDefault (in /usr/lib64/libpython3.10.so.1.0)
 COUT: ==6174==    by 0x1CF76492: ??? (in /usr/lib64/libpython3.10.so.1.0)
 COUT: ==6174==  Address 0xed71320 is 0 bytes inside data symbol "_ZNSs4_Rep20_S_empty_rep_storageE"
 COUT: ==6174==
```

A GDB backtrace looks identical, with slightly more symbol information:

```
 #0  __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
 #1  0x00007fe519095893 in __pthread_kill_internal (signo=6, threadid=<optimized out>) at pthread_kill.c:78
 cocotb#2  0x00007fe519042846 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
 cocotb#3  0x00007fe51902b81c in __GI_abort () at abort.c:79
 cocotb#4  0x00007fe5190889ae in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7fe5191b144f "%s\n") at ../sysdeps/posix/libc_fatal.c:155
 cocotb#5  0x00007fe5190a014c in malloc_printerr (str=str@entry=0x7fe5191af0a9 "free(): invalid pointer") at malloc.c:5660
 cocotb#6  0x00007fe5190a211c in _int_free (av=<optimized out>, p=<optimized out>, have_lock=have_lock@entry=0) at malloc.c:4435
 cocotb#7  0x00007fe5190a4b13 in __GI___libc_free (mem=<optimized out>) at malloc.c:3385
 cocotb#8  0x00007fe514f9ea91 in std::string::assign(std::string const&) ()
 from /home/philipp/src/cocotb-riviera-debug-3078-binary/.direnv/python-3.10.7/lib64/python3.10/site-packages/cocotb/libs/libgpilog.so
 cocotb#9  0x00007fe514fbe875 in std::string::operator= (__str=..., this=0x7fe50e0d2d58) at /opt/rh/devtoolset-10/root/usr/include/c++/10/bits/basic_string.h:3726
 cocotb#10 GpiObjHdl::initialise (this=0x7fe50e0d2d30, name=..., fq_name=...) at cocotb/share/lib/gpi/GpiCbHdl.cpp:74
 cocotb#11 0x00007fe514f761b3 in VhpiImpl::create_gpi_obj_from_handle (this=0x7fe50c17df00, new_hdl=<optimized out>, name=..., fq_name=...) at cocotb/share/lib/vhpi/VhpiImpl.cpp:462
 cocotb#12 0x00007fe514f796cb in VhpiImpl::native_check_create (this=0x7fe50c17df00, name=..., parent=<optimized out>) at cocotb/share/lib/vhpi/VhpiImpl.cpp:575
 cocotb#13 0x00007fe514fc1955 in gpi_get_handle_by_name_ (skip_impl=0x0, name=..., parent=0x7fe50c0b9ea0) at cocotb/share/lib/gpi/GpiCommon.cpp:297
 cocotb#14 gpi_get_handle_by_name_ (parent=0x7fe50c0b9ea0, name=..., skip_impl=0x0) at cocotb/share/lib/gpi/GpiCommon.cpp:260
 cocotb#15 0x00007fe514fc1b01 in gpi_get_handle_by_name (base=0x7fe50c0b9ea0, name=0x7fe5001192a0 "i_swapper_vhdl") at cocotb/share/lib/gpi/GpiCommon.cpp:339
 cocotb#16 0x00007fe5141136c6 in get_handle_by_name (self=0x7fe5000c07f0, args=<optimized out>) at cocotb/share/lib/simulator/simulatormodule.cpp:681
 cocotb#17 0x00007fe51471d51b in method_vectorcall_VARARGS (func=<method_descriptor at remote 0x7fe514193970>, args=0x7fe5000f4ee8, nargsf=<optimized out>, kwnames=0x0)
 at Objects/descrobject.c:311
```

This Valgrind report indicates that `free()` is called on an object which isn't
intended ot be freed, and that's
`std::basic_string<char, std::char_traits<char>, std::allocator<char>>::_Rep::_S_empty_rep_storage`
in this case.

This symbol within libstdc++ is documented as
(https://github.com/gcc-mirror/gcc/blob/releases/gcc-10/libstdc++-v3/include/bits/basic_string.h#L3230):

```
	// The following storage is init'd to 0 by the linker, resulting
        // (carefully) in an empty string with one reference.
        static size_type _S_empty_rep_storage[];
```

What seems to happen is that when we call

```
int GpiObjHdl::initialise(const std::string &name, const std::string &fq_name) {
    m_name = name;
    ...
}
```

`m_name` gets free()'d after it got the new `name` assigned. Since
`m_name` was empty/unset before, free() tries to access
`_S_empty_rep_storage`.

Assigning an explicit default value to `m_name` works around the problem
nicely.

That being said, it's unclear why free() is getting invoked on that symbol
at all. It's also unclear why the same code only causes issues for a
single mixed signal testcase. Finding out is unlikely to be trivial:
cocotb wheels link (parts of) a static libstdc++ from RHEL7, while
Riviera-PRO comes with its own dynamically-linked libstdc++. It's my
hope that the workaround in this commit serves us long enough before it
becomes a problem in itself.

Fixes cocotb#3078
imphil added a commit that referenced this issue Oct 13, 2022
cocotb crashes when running the mixed language example with Riviera-PRO,
using a Verilog toplevel and the pre-built binary wheels (manylinux2014,
built on CentOS7).

Valgrind reports

```
 COUT: ==6174== Invalid free() / delete / delete[] / realloc()
 COUT: ==6174==    at 0xC78271B: operator delete(void*) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
 COUT: ==6174==    by 0x1CE1AC80: std::string::assign(std::string const&) (in /home/philipp/src/cocotb-riviera-debug-3078-binary/.direnv/python-3.10.7/lib/python3.10/site-packages/cocotb/libs/libgpilog.so)
 COUT: ==6174==    by 0x1CDE56C6: GpiObjHdl::initialise(std::string const&, std::string const&) (GpiCbHdl.cpp:74)
 COUT: ==6174==    by 0x1CE3D587: VhpiObjHdl::initialise(std::string const&, std::string const&) (VhpiCbHdl.cpp:258)
 COUT: ==6174==    by 0x1CE46932: VhpiImpl::create_gpi_obj_from_handle(unsigned int*, std::string&, std::string&) (VhpiImpl.cpp:462)
 COUT: ==6174==    by 0x1CE470E5: VhpiImpl::native_check_create(std::string&, GpiObjHdl*) (VhpiImpl.cpp:575)
 COUT: ==6174==    by 0x1CDE6E1E: gpi_get_handle_by_name_(GpiObjHdl*, std::string, GpiImplInterface*) (GpiCommon.cpp:297)
 COUT: ==6174==    by 0x1CDE711C: gpi_get_handle_by_name (GpiCommon.cpp:339)
 COUT: ==6174==    by 0x14BF9595: get_handle_by_name((anonymous namespace)::gpi_hdl_Object<GpiObjHdl*>*, _object*) (simulatormodule.cpp:681)
 COUT: ==6174==    by 0x1CF7351A: ??? (in /usr/lib64/libpython3.10.so.1.0)
 COUT: ==6174==    by 0x1CF77976: _PyEval_EvalFrameDefault (in /usr/lib64/libpython3.10.so.1.0)
 COUT: ==6174==    by 0x1CF76492: ??? (in /usr/lib64/libpython3.10.so.1.0)
 COUT: ==6174==  Address 0xed71320 is 0 bytes inside data symbol "_ZNSs4_Rep20_S_empty_rep_storageE"
 COUT: ==6174==
```

A GDB backtrace looks identical, with slightly more symbol information:

```
 #0  __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
 #1  0x00007fe519095893 in __pthread_kill_internal (signo=6, threadid=<optimized out>) at pthread_kill.c:78
 #2  0x00007fe519042846 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
 #3  0x00007fe51902b81c in __GI_abort () at abort.c:79
 #4  0x00007fe5190889ae in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7fe5191b144f "%s\n") at ../sysdeps/posix/libc_fatal.c:155
 #5  0x00007fe5190a014c in malloc_printerr (str=str@entry=0x7fe5191af0a9 "free(): invalid pointer") at malloc.c:5660
 #6  0x00007fe5190a211c in _int_free (av=<optimized out>, p=<optimized out>, have_lock=have_lock@entry=0) at malloc.c:4435
 #7  0x00007fe5190a4b13 in __GI___libc_free (mem=<optimized out>) at malloc.c:3385
 #8  0x00007fe514f9ea91 in std::string::assign(std::string const&) ()
 from /home/philipp/src/cocotb-riviera-debug-3078-binary/.direnv/python-3.10.7/lib64/python3.10/site-packages/cocotb/libs/libgpilog.so
 #9  0x00007fe514fbe875 in std::string::operator= (__str=..., this=0x7fe50e0d2d58) at /opt/rh/devtoolset-10/root/usr/include/c++/10/bits/basic_string.h:3726
 #10 GpiObjHdl::initialise (this=0x7fe50e0d2d30, name=..., fq_name=...) at cocotb/share/lib/gpi/GpiCbHdl.cpp:74
 #11 0x00007fe514f761b3 in VhpiImpl::create_gpi_obj_from_handle (this=0x7fe50c17df00, new_hdl=<optimized out>, name=..., fq_name=...) at cocotb/share/lib/vhpi/VhpiImpl.cpp:462
 #12 0x00007fe514f796cb in VhpiImpl::native_check_create (this=0x7fe50c17df00, name=..., parent=<optimized out>) at cocotb/share/lib/vhpi/VhpiImpl.cpp:575
 #13 0x00007fe514fc1955 in gpi_get_handle_by_name_ (skip_impl=0x0, name=..., parent=0x7fe50c0b9ea0) at cocotb/share/lib/gpi/GpiCommon.cpp:297
 #14 gpi_get_handle_by_name_ (parent=0x7fe50c0b9ea0, name=..., skip_impl=0x0) at cocotb/share/lib/gpi/GpiCommon.cpp:260
 #15 0x00007fe514fc1b01 in gpi_get_handle_by_name (base=0x7fe50c0b9ea0, name=0x7fe5001192a0 "i_swapper_vhdl") at cocotb/share/lib/gpi/GpiCommon.cpp:339
 #16 0x00007fe5141136c6 in get_handle_by_name (self=0x7fe5000c07f0, args=<optimized out>) at cocotb/share/lib/simulator/simulatormodule.cpp:681
 #17 0x00007fe51471d51b in method_vectorcall_VARARGS (func=<method_descriptor at remote 0x7fe514193970>, args=0x7fe5000f4ee8, nargsf=<optimized out>, kwnames=0x0)
 at Objects/descrobject.c:311
```

This Valgrind report indicates that `free()` is called on an object which isn't
intended ot be freed, and that's
`std::basic_string<char, std::char_traits<char>, std::allocator<char>>::_Rep::_S_empty_rep_storage`
in this case.

This symbol within libstdc++ is documented as
(https://github.com/gcc-mirror/gcc/blob/releases/gcc-10/libstdc++-v3/include/bits/basic_string.h#L3230):

```
	// The following storage is init'd to 0 by the linker, resulting
        // (carefully) in an empty string with one reference.
        static size_type _S_empty_rep_storage[];
```

What seems to happen is that when we call

```
int GpiObjHdl::initialise(const std::string &name, const std::string &fq_name) {
    m_name = name;
    ...
}
```

`m_name` gets free()'d after it got the new `name` assigned. Since
`m_name` was empty/unset before, free() tries to access
`_S_empty_rep_storage`.

Assigning an explicit default value to `m_name` works around the problem
nicely.

That being said, it's unclear why free() is getting invoked on that symbol
at all. It's also unclear why the same code only causes issues for a
single mixed signal testcase. Finding out is unlikely to be trivial:
cocotb wheels link (parts of) a static libstdc++ from RHEL7, while
Riviera-PRO comes with its own dynamically-linked libstdc++. It's my
hope that the workaround in this commit serves us long enough before it
becomes a problem in itself.

Fixes #3078
imphil added a commit to imphil/cocotb that referenced this issue Nov 10, 2022
cocotb crashes when running the mixed language example with Riviera-PRO,
using a Verilog toplevel and the pre-built binary wheels (manylinux2014,
built on CentOS7).

Valgrind reports

```
 COUT: ==6174== Invalid free() / delete / delete[] / realloc()
 COUT: ==6174==    at 0xC78271B: operator delete(void*) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
 COUT: ==6174==    by 0x1CE1AC80: std::string::assign(std::string const&) (in /home/philipp/src/cocotb-riviera-debug-3078-binary/.direnv/python-3.10.7/lib/python3.10/site-packages/cocotb/libs/libgpilog.so)
 COUT: ==6174==    by 0x1CDE56C6: GpiObjHdl::initialise(std::string const&, std::string const&) (GpiCbHdl.cpp:74)
 COUT: ==6174==    by 0x1CE3D587: VhpiObjHdl::initialise(std::string const&, std::string const&) (VhpiCbHdl.cpp:258)
 COUT: ==6174==    by 0x1CE46932: VhpiImpl::create_gpi_obj_from_handle(unsigned int*, std::string&, std::string&) (VhpiImpl.cpp:462)
 COUT: ==6174==    by 0x1CE470E5: VhpiImpl::native_check_create(std::string&, GpiObjHdl*) (VhpiImpl.cpp:575)
 COUT: ==6174==    by 0x1CDE6E1E: gpi_get_handle_by_name_(GpiObjHdl*, std::string, GpiImplInterface*) (GpiCommon.cpp:297)
 COUT: ==6174==    by 0x1CDE711C: gpi_get_handle_by_name (GpiCommon.cpp:339)
 COUT: ==6174==    by 0x14BF9595: get_handle_by_name((anonymous namespace)::gpi_hdl_Object<GpiObjHdl*>*, _object*) (simulatormodule.cpp:681)
 COUT: ==6174==    by 0x1CF7351A: ??? (in /usr/lib64/libpython3.10.so.1.0)
 COUT: ==6174==    by 0x1CF77976: _PyEval_EvalFrameDefault (in /usr/lib64/libpython3.10.so.1.0)
 COUT: ==6174==    by 0x1CF76492: ??? (in /usr/lib64/libpython3.10.so.1.0)
 COUT: ==6174==  Address 0xed71320 is 0 bytes inside data symbol "_ZNSs4_Rep20_S_empty_rep_storageE"
 COUT: ==6174==
```

A GDB backtrace looks identical, with slightly more symbol information:

```
 #0  __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
 #1  0x00007fe519095893 in __pthread_kill_internal (signo=6, threadid=<optimized out>) at pthread_kill.c:78
 cocotb#2  0x00007fe519042846 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
 cocotb#3  0x00007fe51902b81c in __GI_abort () at abort.c:79
 cocotb#4  0x00007fe5190889ae in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7fe5191b144f "%s\n") at ../sysdeps/posix/libc_fatal.c:155
 cocotb#5  0x00007fe5190a014c in malloc_printerr (str=str@entry=0x7fe5191af0a9 "free(): invalid pointer") at malloc.c:5660
 cocotb#6  0x00007fe5190a211c in _int_free (av=<optimized out>, p=<optimized out>, have_lock=have_lock@entry=0) at malloc.c:4435
 cocotb#7  0x00007fe5190a4b13 in __GI___libc_free (mem=<optimized out>) at malloc.c:3385
 cocotb#8  0x00007fe514f9ea91 in std::string::assign(std::string const&) ()
 from /home/philipp/src/cocotb-riviera-debug-3078-binary/.direnv/python-3.10.7/lib64/python3.10/site-packages/cocotb/libs/libgpilog.so
 cocotb#9  0x00007fe514fbe875 in std::string::operator= (__str=..., this=0x7fe50e0d2d58) at /opt/rh/devtoolset-10/root/usr/include/c++/10/bits/basic_string.h:3726
 cocotb#10 GpiObjHdl::initialise (this=0x7fe50e0d2d30, name=..., fq_name=...) at cocotb/share/lib/gpi/GpiCbHdl.cpp:74
 cocotb#11 0x00007fe514f761b3 in VhpiImpl::create_gpi_obj_from_handle (this=0x7fe50c17df00, new_hdl=<optimized out>, name=..., fq_name=...) at cocotb/share/lib/vhpi/VhpiImpl.cpp:462
 cocotb#12 0x00007fe514f796cb in VhpiImpl::native_check_create (this=0x7fe50c17df00, name=..., parent=<optimized out>) at cocotb/share/lib/vhpi/VhpiImpl.cpp:575
 cocotb#13 0x00007fe514fc1955 in gpi_get_handle_by_name_ (skip_impl=0x0, name=..., parent=0x7fe50c0b9ea0) at cocotb/share/lib/gpi/GpiCommon.cpp:297
 cocotb#14 gpi_get_handle_by_name_ (parent=0x7fe50c0b9ea0, name=..., skip_impl=0x0) at cocotb/share/lib/gpi/GpiCommon.cpp:260
 cocotb#15 0x00007fe514fc1b01 in gpi_get_handle_by_name (base=0x7fe50c0b9ea0, name=0x7fe5001192a0 "i_swapper_vhdl") at cocotb/share/lib/gpi/GpiCommon.cpp:339
 cocotb#16 0x00007fe5141136c6 in get_handle_by_name (self=0x7fe5000c07f0, args=<optimized out>) at cocotb/share/lib/simulator/simulatormodule.cpp:681
 cocotb#17 0x00007fe51471d51b in method_vectorcall_VARARGS (func=<method_descriptor at remote 0x7fe514193970>, args=0x7fe5000f4ee8, nargsf=<optimized out>, kwnames=0x0)
 at Objects/descrobject.c:311
```

This Valgrind report indicates that `free()` is called on an object which isn't
intended ot be freed, and that's
`std::basic_string<char, std::char_traits<char>, std::allocator<char>>::_Rep::_S_empty_rep_storage`
in this case.

This symbol within libstdc++ is documented as
(https://github.com/gcc-mirror/gcc/blob/releases/gcc-10/libstdc++-v3/include/bits/basic_string.h#L3230):

```
	// The following storage is init'd to 0 by the linker, resulting
        // (carefully) in an empty string with one reference.
        static size_type _S_empty_rep_storage[];
```

What seems to happen is that when we call

```
int GpiObjHdl::initialise(const std::string &name, const std::string &fq_name) {
    m_name = name;
    ...
}
```

`m_name` gets free()'d after it got the new `name` assigned. Since
`m_name` was empty/unset before, free() tries to access
`_S_empty_rep_storage`.

Assigning an explicit default value to `m_name` works around the problem
nicely.

That being said, it's unclear why free() is getting invoked on that symbol
at all. It's also unclear why the same code only causes issues for a
single mixed signal testcase. Finding out is unlikely to be trivial:
cocotb wheels link (parts of) a static libstdc++ from RHEL7, while
Riviera-PRO comes with its own dynamically-linked libstdc++. It's my
hope that the workaround in this commit serves us long enough before it
becomes a problem in itself.

Fixes cocotb#3078
imphil added a commit that referenced this issue Nov 12, 2022
cocotb crashes when running the mixed language example with Riviera-PRO,
using a Verilog toplevel and the pre-built binary wheels (manylinux2014,
built on CentOS7).

Valgrind reports

```
 COUT: ==6174== Invalid free() / delete / delete[] / realloc()
 COUT: ==6174==    at 0xC78271B: operator delete(void*) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
 COUT: ==6174==    by 0x1CE1AC80: std::string::assign(std::string const&) (in /home/philipp/src/cocotb-riviera-debug-3078-binary/.direnv/python-3.10.7/lib/python3.10/site-packages/cocotb/libs/libgpilog.so)
 COUT: ==6174==    by 0x1CDE56C6: GpiObjHdl::initialise(std::string const&, std::string const&) (GpiCbHdl.cpp:74)
 COUT: ==6174==    by 0x1CE3D587: VhpiObjHdl::initialise(std::string const&, std::string const&) (VhpiCbHdl.cpp:258)
 COUT: ==6174==    by 0x1CE46932: VhpiImpl::create_gpi_obj_from_handle(unsigned int*, std::string&, std::string&) (VhpiImpl.cpp:462)
 COUT: ==6174==    by 0x1CE470E5: VhpiImpl::native_check_create(std::string&, GpiObjHdl*) (VhpiImpl.cpp:575)
 COUT: ==6174==    by 0x1CDE6E1E: gpi_get_handle_by_name_(GpiObjHdl*, std::string, GpiImplInterface*) (GpiCommon.cpp:297)
 COUT: ==6174==    by 0x1CDE711C: gpi_get_handle_by_name (GpiCommon.cpp:339)
 COUT: ==6174==    by 0x14BF9595: get_handle_by_name((anonymous namespace)::gpi_hdl_Object<GpiObjHdl*>*, _object*) (simulatormodule.cpp:681)
 COUT: ==6174==    by 0x1CF7351A: ??? (in /usr/lib64/libpython3.10.so.1.0)
 COUT: ==6174==    by 0x1CF77976: _PyEval_EvalFrameDefault (in /usr/lib64/libpython3.10.so.1.0)
 COUT: ==6174==    by 0x1CF76492: ??? (in /usr/lib64/libpython3.10.so.1.0)
 COUT: ==6174==  Address 0xed71320 is 0 bytes inside data symbol "_ZNSs4_Rep20_S_empty_rep_storageE"
 COUT: ==6174==
```

A GDB backtrace looks identical, with slightly more symbol information:

```
 #0  __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
 #1  0x00007fe519095893 in __pthread_kill_internal (signo=6, threadid=<optimized out>) at pthread_kill.c:78
 #2  0x00007fe519042846 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
 #3  0x00007fe51902b81c in __GI_abort () at abort.c:79
 #4  0x00007fe5190889ae in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7fe5191b144f "%s\n") at ../sysdeps/posix/libc_fatal.c:155
 #5  0x00007fe5190a014c in malloc_printerr (str=str@entry=0x7fe5191af0a9 "free(): invalid pointer") at malloc.c:5660
 #6  0x00007fe5190a211c in _int_free (av=<optimized out>, p=<optimized out>, have_lock=have_lock@entry=0) at malloc.c:4435
 #7  0x00007fe5190a4b13 in __GI___libc_free (mem=<optimized out>) at malloc.c:3385
 #8  0x00007fe514f9ea91 in std::string::assign(std::string const&) ()
 from /home/philipp/src/cocotb-riviera-debug-3078-binary/.direnv/python-3.10.7/lib64/python3.10/site-packages/cocotb/libs/libgpilog.so
 #9  0x00007fe514fbe875 in std::string::operator= (__str=..., this=0x7fe50e0d2d58) at /opt/rh/devtoolset-10/root/usr/include/c++/10/bits/basic_string.h:3726
 #10 GpiObjHdl::initialise (this=0x7fe50e0d2d30, name=..., fq_name=...) at cocotb/share/lib/gpi/GpiCbHdl.cpp:74
 #11 0x00007fe514f761b3 in VhpiImpl::create_gpi_obj_from_handle (this=0x7fe50c17df00, new_hdl=<optimized out>, name=..., fq_name=...) at cocotb/share/lib/vhpi/VhpiImpl.cpp:462
 #12 0x00007fe514f796cb in VhpiImpl::native_check_create (this=0x7fe50c17df00, name=..., parent=<optimized out>) at cocotb/share/lib/vhpi/VhpiImpl.cpp:575
 #13 0x00007fe514fc1955 in gpi_get_handle_by_name_ (skip_impl=0x0, name=..., parent=0x7fe50c0b9ea0) at cocotb/share/lib/gpi/GpiCommon.cpp:297
 #14 gpi_get_handle_by_name_ (parent=0x7fe50c0b9ea0, name=..., skip_impl=0x0) at cocotb/share/lib/gpi/GpiCommon.cpp:260
 #15 0x00007fe514fc1b01 in gpi_get_handle_by_name (base=0x7fe50c0b9ea0, name=0x7fe5001192a0 "i_swapper_vhdl") at cocotb/share/lib/gpi/GpiCommon.cpp:339
 #16 0x00007fe5141136c6 in get_handle_by_name (self=0x7fe5000c07f0, args=<optimized out>) at cocotb/share/lib/simulator/simulatormodule.cpp:681
 #17 0x00007fe51471d51b in method_vectorcall_VARARGS (func=<method_descriptor at remote 0x7fe514193970>, args=0x7fe5000f4ee8, nargsf=<optimized out>, kwnames=0x0)
 at Objects/descrobject.c:311
```

This Valgrind report indicates that `free()` is called on an object which isn't
intended ot be freed, and that's
`std::basic_string<char, std::char_traits<char>, std::allocator<char>>::_Rep::_S_empty_rep_storage`
in this case.

This symbol within libstdc++ is documented as
(https://github.com/gcc-mirror/gcc/blob/releases/gcc-10/libstdc++-v3/include/bits/basic_string.h#L3230):

```
	// The following storage is init'd to 0 by the linker, resulting
        // (carefully) in an empty string with one reference.
        static size_type _S_empty_rep_storage[];
```

What seems to happen is that when we call

```
int GpiObjHdl::initialise(const std::string &name, const std::string &fq_name) {
    m_name = name;
    ...
}
```

`m_name` gets free()'d after it got the new `name` assigned. Since
`m_name` was empty/unset before, free() tries to access
`_S_empty_rep_storage`.

Assigning an explicit default value to `m_name` works around the problem
nicely.

That being said, it's unclear why free() is getting invoked on that symbol
at all. It's also unclear why the same code only causes issues for a
single mixed signal testcase. Finding out is unlikely to be trivial:
cocotb wheels link (parts of) a static libstdc++ from RHEL7, while
Riviera-PRO comes with its own dynamically-linked libstdc++. It's my
hope that the workaround in this commit serves us long enough before it
becomes a problem in itself.

Fixes #3078
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
category:docs documentation issues and fixes
Projects
None yet
Development

No branches or pull requests

4 participants