ghdl / ghdl

VHDL 2008/93/87 simulator
GNU General Public License v2.0
2.37k stars 362 forks source link

generated executable crashes with seg fault on wide std_logic_vector signal with declared init value #1112

Open roeekalinsky opened 4 years ago

roeekalinsky commented 4 years ago

Description When the width of a std_logic_vector signal exceeds a certain size and has an initialization value in the declaration, the ghdl generated executable crashes with a segmentation fault.

Expected behaviour The ghdl generated executable should not crash, should not generate a segmentation fault.

How to reproduce? A minimal working example is provided in the form of a trivial VHDL entity and a shell script that demonstrates configurations that work correctly and then configurations where it crashes as described above.

example.vhd:

library ieee;
use ieee.std_logic_1164.all;

entity example is
  generic (
    VEC_WIDTH : positive);
end example;

architecture behavioral of example is
  signal vec : std_logic_vector(VEC_WIDTH-1 downto 0) := (others => '0');
begin
end behavioral;

example.sh:

rm -rf ghdl_worklibs
mkdir  ghdl_worklibs

rm -rf ghdl_worklibs/example_lib
mkdir  ghdl_worklibs/example_lib

rm -rf ghdl_bin
mkdir  ghdl_bin

rm -rf strace_logs
mkdir  strace_logs

ghdl -a -Wno-hide  -Pghdl_worklibs/example_lib --workdir=ghdl_worklibs/example_lib --work=example_lib ./example.vhd

ghdl -e -Pghdl_worklibs/example_lib --workdir=ghdl_worklibs/example_lib --work=example_lib -o ghdl_bin/example example

# These configurations are ok.
#
# Note: Looking at strace, it looks like an amount of memory allocated equals
# round_up_to_power_of_two(8*VEC_WIDTH) + 4096
#
#                                                                                          # memory size allocated:
strace ghdl_bin/example --no-run -gVEC_WIDTH=1048576   &> strace_logs/strace_log_1m.txt    #              8392704 (0x0000000000801000)
strace ghdl_bin/example --no-run -gVEC_WIDTH=2097152   &> strace_logs/strace_log_2m.txt    #             16781312 (0x0000000001001000)
strace ghdl_bin/example --no-run -gVEC_WIDTH=4194304   &> strace_logs/strace_log_4m.txt    #             33558528 (0x0000000002001000)

# These cause crash / segmentation fault (SIGSEGV)
strace ghdl_bin/example --no-run -gVEC_WIDTH=8388608   &> strace_logs/strace_log_8m.txt    #             67112960 (0x0000000004001000)
strace ghdl_bin/example --no-run -gVEC_WIDTH=16777216  &> strace_logs/strace_log_16m.txt   #            134221824 (0x0000000008001000)
strace ghdl_bin/example --no-run -gVEC_WIDTH=33554432  &> strace_logs/strace_log_32m.txt   #            268439552 (0x0000000010001000)

Context

tgingold commented 4 years ago

This is a known issue: it happens when some data are temporary allocated on the stack.

eine commented 4 years ago

@roeekalinsky, see #822. This is probably related to #752 too.

roeekalinsky commented 4 years ago

@tgingold, looks like you are correct about it being a stack overflow issue. The size threshold for crash is dependent on the stack size limit set in the OS (ulimit -s). So, here's a revised version of my bug report:

Description When the width of a std_logic_vector signal exceeds a certain size and has an initialization value in the declaration, the ghdl generated executable crashes with a segmentation fault. The signal size threshold for inducing a crash / seg fault depends on the stack size limit in the OS.

Expected behaviour The ghdl executable should not crash, should not generate a segmentation fault. Preferably, ghdl should be able to handle any arbitrary signal size (possibly by not using the stack this way). But at a minimum, if a signal size limit exists and is exceeded, the ghdl executable should detect this condition and exit gracefully with a meaningful error message, not just crash with a segmentation fault.

How to reproduce? A minimal working example is provided in the form of 1) a trivial VHDL entity, 2) a shell script that runs configurations that work correctly and then configurations where it crashes with different stack size limits as described above, and 3) a console log of the output produced by running the shell script.

example.vhd:

library ieee;
use ieee.std_logic_1164.all;

entity example is
  generic (
    VEC_WIDTH : positive);
end example;

architecture behavioral of example is
  signal vec : std_logic_vector(VEC_WIDTH-1 downto 0) := (others => '0');
begin
end behavioral;

example.sh:

rm -rf ghdl_worklibs
mkdir  ghdl_worklibs

rm -rf ghdl_worklibs/example_lib
mkdir  ghdl_worklibs/example_lib

rm -rf ghdl_bin
mkdir  ghdl_bin

ghdl -a -Wno-hide  -Pghdl_worklibs/example_lib --workdir=ghdl_worklibs/example_lib --work=example_lib ./example.vhd

ghdl -e -Pghdl_worklibs/example_lib --workdir=ghdl_worklibs/example_lib --work=example_lib -o ghdl_bin/example example

echo "Set stack size to 64 MB, run VEC_WIDTH=1M, 2M, 4M, 8M, 16M, 32M:"
ulimit -s 65536
ghdl_bin/example --no-run -gVEC_WIDTH=1048576
ghdl_bin/example --no-run -gVEC_WIDTH=2097152
ghdl_bin/example --no-run -gVEC_WIDTH=4194304
ghdl_bin/example --no-run -gVEC_WIDTH=8388608
ghdl_bin/example --no-run -gVEC_WIDTH=16777216
ghdl_bin/example --no-run -gVEC_WIDTH=33554432
echo "Done."
echo ""

echo "Set stack size to 32 MB, run VEC_WIDTH=1M, 2M, 4M, 8M, 16M, 32M:"
ulimit -s 32768
ghdl_bin/example --no-run -gVEC_WIDTH=1048576
ghdl_bin/example --no-run -gVEC_WIDTH=2097152
ghdl_bin/example --no-run -gVEC_WIDTH=4194304
ghdl_bin/example --no-run -gVEC_WIDTH=8388608
ghdl_bin/example --no-run -gVEC_WIDTH=16777216
ghdl_bin/example --no-run -gVEC_WIDTH=33554432
echo "Done."
echo ""

echo "Set stack size to 16 MB, run VEC_WIDTH=1M, 2M, 4M, 8M, 16M, 32M:"
ulimit -s 16384
ghdl_bin/example --no-run -gVEC_WIDTH=1048576
ghdl_bin/example --no-run -gVEC_WIDTH=2097152
ghdl_bin/example --no-run -gVEC_WIDTH=4194304
ghdl_bin/example --no-run -gVEC_WIDTH=8388608
ghdl_bin/example --no-run -gVEC_WIDTH=16777216
ghdl_bin/example --no-run -gVEC_WIDTH=33554432
echo "Done."
echo ""

echo "Set stack size to 8 MB, run VEC_WIDTH=1M, 2M, 4M, 8M, 16M, 32M:"
ulimit -s 8192
ghdl_bin/example --no-run -gVEC_WIDTH=1048576
ghdl_bin/example --no-run -gVEC_WIDTH=2097152
ghdl_bin/example --no-run -gVEC_WIDTH=4194304
ghdl_bin/example --no-run -gVEC_WIDTH=8388608
ghdl_bin/example --no-run -gVEC_WIDTH=16777216
ghdl_bin/example --no-run -gVEC_WIDTH=33554432
echo "Done."
echo ""

echo "Set stack size to 4 MB, run VEC_WIDTH=1M, 2M, 4M, 8M, 16M, 32M:"
ulimit -s 4096
ghdl_bin/example --no-run -gVEC_WIDTH=1048576
ghdl_bin/example --no-run -gVEC_WIDTH=2097152
ghdl_bin/example --no-run -gVEC_WIDTH=4194304
ghdl_bin/example --no-run -gVEC_WIDTH=8388608
ghdl_bin/example --no-run -gVEC_WIDTH=16777216
ghdl_bin/example --no-run -gVEC_WIDTH=33554432
echo "Done."
echo ""

echo "Set stack size to 2 MB, run VEC_WIDTH=1M, 2M, 4M, 8M, 16M, 32M:"
ulimit -s 2048
ghdl_bin/example --no-run -gVEC_WIDTH=1048576
ghdl_bin/example --no-run -gVEC_WIDTH=2097152
ghdl_bin/example --no-run -gVEC_WIDTH=4194304
ghdl_bin/example --no-run -gVEC_WIDTH=8388608
ghdl_bin/example --no-run -gVEC_WIDTH=16777216
ghdl_bin/example --no-run -gVEC_WIDTH=33554432
echo "Done."
echo ""

echo "Set stack size to 1 MB, run VEC_WIDTH=1M, 2M, 4M, 8M, 16M, 32M:"
ulimit -s 1024
ghdl_bin/example --no-run -gVEC_WIDTH=1048576
ghdl_bin/example --no-run -gVEC_WIDTH=2097152
ghdl_bin/example --no-run -gVEC_WIDTH=4194304
ghdl_bin/example --no-run -gVEC_WIDTH=8388608
ghdl_bin/example --no-run -gVEC_WIDTH=16777216
ghdl_bin/example --no-run -gVEC_WIDTH=33554432
echo "Done."
echo ""

console log:

[kalinskyr@roees-work-laptop ghdl_segfault_bug]$ ./example.sh
Set stack size to 64 MB, run VEC_WIDTH=1M, 2M, 4M, 8M, 16M, 32M:
Done.

Set stack size to 32 MB, run VEC_WIDTH=1M, 2M, 4M, 8M, 16M, 32M:
./example.sh: line 32: 11905 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=33554432
Done.

Set stack size to 16 MB, run VEC_WIDTH=1M, 2M, 4M, 8M, 16M, 32M:
./example.sh: line 42: 11922 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=16777216
./example.sh: line 43: 11924 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=33554432
Done.

Set stack size to 8 MB, run VEC_WIDTH=1M, 2M, 4M, 8M, 16M, 32M:
./example.sh: line 52: 11929 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=8388608
./example.sh: line 53: 11931 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=16777216
./example.sh: line 54: 11933 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=33554432
Done.

Set stack size to 4 MB, run VEC_WIDTH=1M, 2M, 4M, 8M, 16M, 32M:
./example.sh: line 62: 11938 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=4194304
./example.sh: line 63: 11940 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=8388608
./example.sh: line 64: 11945 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=16777216
./example.sh: line 65: 11947 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=33554432
Done.

Set stack size to 2 MB, run VEC_WIDTH=1M, 2M, 4M, 8M, 16M, 32M:
./example.sh: line 72: 11950 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=2097152
./example.sh: line 73: 11952 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=4194304
./example.sh: line 74: 11954 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=8388608
./example.sh: line 75: 11956 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=16777216
./example.sh: line 76: 11958 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=33554432
Done.

Set stack size to 1 MB, run VEC_WIDTH=1M, 2M, 4M, 8M, 16M, 32M:
./example.sh: line 82: 11960 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=1048576
./example.sh: line 83: 11962 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=2097152
./example.sh: line 84: 11964 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=4194304
./example.sh: line 85: 11966 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=8388608
./example.sh: line 86: 11968 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=16777216
./example.sh: line 87: 11970 Segmentation fault      (core dumped) ghdl_bin/example --no-run -gVEC_WIDTH=33554432
Done.

[kalinskyr@roees-work-laptop ghdl_segfault_bug]$

Context

eine commented 4 years ago

Ref January 21, 2020 4:16 PM