Report double calls to vpi_release_handle when using VL_DEBUG

This commit is contained in:
Wilson Snyder 2020-12-16 19:10:17 -05:00
parent d5d6598d75
commit ff702174d8
6 changed files with 94 additions and 4 deletions

View File

@ -56,6 +56,13 @@ constexpr unsigned VL_VPI_LINE_SIZE = 8192;
// Base VPI handled object
class VerilatedVpio VL_NOT_FINAL {
// CONSTANTS
/// Magic value stored in front of object to detect double free etc
/// Must be odd, as aligned pointer can never be odd
#ifdef VL_DEBUG
static constexpr vluint32_t activeMagic() { return 0xfeed100f; }
#endif
// MEM MANGLEMENT
static VL_THREAD_LOCAL vluint8_t* t_freeHead;
@ -73,14 +80,27 @@ public:
if (VL_LIKELY(t_freeHead)) {
vluint8_t* newp = t_freeHead;
t_freeHead = *(reinterpret_cast<vluint8_t**>(newp));
#ifdef VL_DEBUG
*(reinterpret_cast<vluint32_t*>(newp)) = activeMagic();
#endif
return newp + 8;
}
// +8: 8 bytes for next
vluint8_t* newp = reinterpret_cast<vluint8_t*>(::operator new(chunk + 8));
#ifdef VL_DEBUG
*(reinterpret_cast<vluint32_t*>(newp)) = activeMagic();
#endif
return newp + 8;
}
static void operator delete(void* obj, size_t /*size*/)VL_MT_SAFE {
vluint8_t* oldp = (static_cast<vluint8_t*>(obj)) - 8;
#ifdef VL_DEBUG
if (VL_UNLIKELY(*(reinterpret_cast<vluint32_t*>(oldp)) != activeMagic())) {
VL_FATAL_MT(__FILE__, __LINE__, "",
"vpi_release_handle() called on same object twice, or on non-Verilator "
"VPI object");
}
#endif
*(reinterpret_cast<void**>(oldp)) = t_freeHead;
t_freeHead = oldp;
}
@ -2003,9 +2023,8 @@ PLI_INT32 vpi_chk_error(p_vpi_error_info error_info_p) {
}
PLI_INT32 vpi_free_object(vpiHandle object) {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
return vpi_release_handle(object); // Deprecated
// vpi_free_object is IEEE deprecated, use vpi_release_handle
return vpi_release_handle(object);
}
PLI_INT32 vpi_release_handle(vpiHandle object) {
@ -2014,6 +2033,7 @@ PLI_INT32 vpi_release_handle(vpiHandle object) {
VerilatedVpio* vop = VerilatedVpio::castp(object);
_VL_VPI_ERROR_RESET();
if (VL_UNLIKELY(!vop)) return 0;
vpi_remove_cb(object); // May not be a callback, but that's ok
VL_DO_DANGLING(delete vop, vop);
return 1;

View File

@ -29,7 +29,7 @@ public:
if (m_handle && m_free) {
// Below not VL_DO_DANGLING so is portable
{
vpi_free_object(m_handle);
vpi_release_handle(m_handle);
m_handle = NULL;
}
}

View File

@ -0,0 +1,2 @@
%Error: /svaha/wsnyder/SandBox/homecvs/v4/verilator/test_regress/../include/verilated_vpi.cpp:99: vpi_release_handle() called on same object twice, or on non-Verilator VPI object
Aborting...

View File

@ -0,0 +1,25 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
compile(
v_flags2 => ["t/$Self->{name}_c.cpp"],
verilator_flags2 => ['--vpi'],
);
execute(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,15 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under The Creative Commons Public Domain, for
// any use, without warranty, 2020 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
import "DPI-C" context function void dpii_check();
module t (/*AUTOARG*/);
initial begin
dpii_check();
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,28 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2009-2011 by Wilson Snyder. This program is free software; you
// can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
//
//*************************************************************************
#include <cstdio>
#include "svdpi.h"
#include "vpi_user.h"
//#include "verilated.h"
#include "Vt_vpi_release_dup_bad__Dpi.h"
//======================================================================
void dpii_check() {
vpiHandle mod; // Not TestVpiHandle as testing double free
// Verilated::scopesDump();
mod = vpi_handle_by_name((PLI_BYTE8*)"top.t", NULL);
if (!mod) vpi_printf(const_cast<char*>("-- Cannot vpi_find module\n"));
vpi_free_object(mod); // using vpi_free_object instead of vpi_release_handle for coverage
vpi_free_object(mod); // error: double free
}