I’ve looked at the compiler flags
riscv64-unknown-elf-g++ -o .pio\build\sipeed-maix-one-dock\src\exception_test.o -c -std=gnu++17 -mcmodel=medany -mabi=lp64f -march=rv64imafc -fno-common -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -ffast-math -fno-math-errno -fsingle-precision-constant -O2 -ggdb -Wall -Werror=all -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-error=maybe-uninitialized -Wextra -Werror=frame-larger-than=65536 -Wno-unused-parameter -Wno-unused-function -Wno-implicit-fallthrough -Wno-sign-compare -Wno-error=missing-braces -Wno-error=return-type -Wno-error=pointer-sign -Wno-missing-braces -Wno-strict-aliasing -Wno-implicit-fallthrough -Wno-missing-field-initializers -Wno-int-to-pointer-cast -Wno-error=comment -Wno-error=logical-not-parentheses -Wno-error=duplicate-decl-specifier -Wno-error=parentheses -Wno-error=maybe-uninitialized -DPLATFORMIO=50001 -DCONFIG_LOG_ENABLE -DCONFIG_LOG_LEVEL=LOG_INFO -DDEBUG=1 -D__riscv64 -DK210 -DARCH=K210 -DF_CPU=400000000L -Iinclude -Isrc [...] src\exception_test.cpp
and there’s no -fno-exceptions
, so that’s ok.
So next looking for compiler errors in
"C:\Users\Maxi\.platformio\packages\toolchain-kendryte210\bin\riscv64-unknown-elf-gcc.exe" --version
riscv64-unknown-elf-gcc.exe (GCC) 8.2.0
Copyright (C) 2018 Free Software Foundation, Inc.
related to exceptions brings up this
opened 04:26PM - 18 Dec 18 UTC
closed 09:47AM - 20 Dec 18 UTC
I have a problem with exception handling during migration of the gcc from 7.2 to… 8.2.
This simple test, which throws an exception, works correctly on gcc 7.2, but causes an error on 8.2 (only in 32bit version):
```
#include <stdio.h>
int main() {
printf("Warm up\n");
try {
throw 1;
}
catch (...) {
printf("In catch\n");
return 0;
}
printf("Back in main\n");
return 1;
}
```
Compiled with commands (gcc 7.2 similarly):
```
riscv64-unknown-elf-gcc -O2 -g -mcmodel=medany -Wall -Wextra -Werror -march=rv32imc -mabi=ilp32 -c *.c *.cpp *.S
riscv64-unknown-elf-gcc -march=rv32imc -mabi=ilp32 -Tlink.ld \
/opt/riscv-gnu-toolchain-elf/bin/../lib/gcc/riscv64-unknown-elf/8.2.0/rv32imc/ilp32/crti.o \
/opt/riscv-gnu-toolchain-elf/bin/../lib/gcc/riscv64-unknown-elf/8.2.0/rv32imc/ilp32/crtbegin.o \
*.o -nostartfiles \
/opt/riscv-gnu-toolchain-elf/bin/../lib/gcc/riscv64-unknown-elf/8.2.0/rv32imc/ilp32/crtend.o \
/opt/riscv-gnu-toolchain-elf/bin/../lib/gcc/riscv64-unknown-elf/8.2.0/rv32imc/ilp32/crtn.o \
-lstdc++ -lm -o rv32imc-test.elf
```
An error occurs, when program process .eh_frame section from elf:
```
(gdb) bt
#0 classify_object_over_fdes (ob=ob@entry=0x8001fc64 <object>, this_fde=this_fde@entry=0x8001db04) at ../../../../../../riscv-gcc/libgcc/unwind-dw2-fde.h:174
#1 0x800060a8 in init_object (ob=0x8001fc64 <object>) at ../../../../../../riscv-gcc/libgcc/unwind-dw2-fde.c:777
#2 search_object (ob=ob@entry=0x8001fc64 <object>, pc=pc@entry=0x80004c4b <_Unwind_RaiseException+139>) at ../../../../../../riscv-gcc/libgcc/unwind-dw2-fde.c:989
#3 0x8000680c in _Unwind_Find_FDE (pc=0x80004c4b <_Unwind_RaiseException+139>, bases=bases@entry=0xbffffb08) at ../../../../../../riscv-gcc/libgcc/unwind-dw2-fde.c:1066
#4 0x8000393c in uw_frame_state_for (context=context@entry=0xbffff9f0, fs=fs@entry=0xbffff778) at ../../../../../../riscv-gcc/libgcc/unwind-dw2.c:1257
#5 0x80004620 in uw_init_context_1 (context=context@entry=0xbffff9f0, outer_cfa=outer_cfa@entry=0xbfffffa0, outer_ra=0x80018e44 <__cxa_throw+76>,
outer_ra@entry=0x80004c4c <_Unwind_RaiseException+140>) at ../../../../../../riscv-gcc/libgcc/unwind-dw2.c:1586
#6 0x80004c4c in _Unwind_RaiseException (exc=0x80020ad0) at ../../../../../../riscv-gcc/libgcc/unwind.inc:93
#7 0x80018e44 in __cxa_throw ()
#8 0x80017a70 in main () at test.cpp:6
```
According to information from http://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html , the .eh_frame section shall contain 1 or more CFI records, each one contains CIE and 1 or more FDE records.
Generally they start with 4-byte Length field and if it contains the value 0, then this CIE shall be considered as a terminator and processing should stop.
While debugging with gdb everything goes okay about a hundred records (with lengths values of 0x10, 0x20 and others of the same order), until a record with lenght 0x3659bff. It seems that the terminator is missed.
Dumps, produced by readelf, confirms the problem:
`readelf --debug=frames rv32imc-test.elf > rv32imc-test.eh_dump`
Dump of elf, compiled with gcc 7.2 (zero terminator is present):
```
Contents of the .eh_frame section:
...
000015ec 00000018 000015a8 FDE cie=00000048 pc=80018b30..80018b6c
DW_CFA_advance_loc: 4 to 80018b34
DW_CFA_def_cfa_offset: 16
DW_CFA_advance_loc: 4 to 80018b38
DW_CFA_offset: r1 at cfa-4
DW_CFA_advance_loc: 44 to 80018b64
DW_CFA_restore: r1
DW_CFA_advance_loc: 4 to 80018b68
DW_CFA_def_cfa_offset: 0
00001608 ZERO terminator
0000160c 00000010 000015c8 FDE cie=00000048 pc=80013cb0..800140e4
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
00001620 00000010 000015dc FDE cie=00000048 pc=800140e4..800144f4
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
Contents of the .debug_frame section:
...
```
But with gcc 8.2 it is missed:
```
Contents of the .eh_frame section:
...
000016c4 00000018 00001680 FDE cie=00000048 pc=80019440..8001947c
DW_CFA_advance_loc: 4 to 80019444
DW_CFA_def_cfa_offset: 16
DW_CFA_advance_loc: 4 to 80019448
DW_CFA_offset: r1 at cfa-4
DW_CFA_advance_loc: 44 to 80019474
DW_CFA_restore: r1
DW_CFA_advance_loc: 4 to 80019478
DW_CFA_def_cfa_offset: 0
000016e0 00000010 0000169c FDE cie=00000048 pc=80014644..80014a78
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
000016f4 00000010 000016b0 FDE cie=00000048 pc=80014a78..80014e88
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
Contents of the .debug_frame section:
...
```
With gcc 8.2 64-bit (rv64imc), also all is ok:
```
...
00001734 ZERO terminator
...
```
It seems that a problem somewhere in eh_frame section generation, but I can not figure out the exact bug.
which pretty much describes the problem. The Standard C++ library (stdc++
) must be linked before the standard GCC library ( c
, gcc
).
So what is the builder script doing?
LIBS = [
"c", "gcc", "m", "stdc++", "atomic"
]
)
if not env.BoardConfig().get("build.ldscript", ""):
env.Replace(LDSCRIPT_PATH=join(FRAMEWORK_DIR, "lds", "kendryte.ld"))
env.Append(CRTEND=[
join(TOOLCHAIN_DIR, "lib", "gcc", "riscv64-unknown-elf", "8.2.0", "crtend.o"),
join(TOOLCHAIN_DIR, "lib", "gcc", "riscv64-unknown-elf", "8.2.0", "crtn.o")
])
env.Append(LINKCOM=" $CRTEND")
#
# Target: Build Core Library
#
Exactly the wrong order.
To verify this (since I don’t have real hardware to test on), please do:
Find the PlatformIO paltforms folder (C:\Users\<user>\.platformio\platforms
, /home/<user>/.platformio/platforms
, …)
Open the file \kendryte210\builder\frameworks\kendryte-freertos-sdk.py
for edit
Replace line 108 with
"stdc++", "m", "atomic", "gcc", "c"
Clean and recompile the project (pio run -t clean
, pio run -e sipeed-maix-one-dock -t upload
) and recheck output.
The github issue also has a minor error where -lgcc
is mentioned twice. So if the above link order doesn’t work you can try things like
"stdc++", "m", "atomic", "c", "gcc"
or the exact replication
"stdc++", "m", "atomic", "gcc", "c", "gcc"
which looks weird but okay.