D.gnu - Exceptions in ARM
- Timo Sintonen (8/8) Jan 01 2014 I started to update minlibd with gdc head from last saturday.
- Iain Buclaw (7/10) Jan 01 2014 testing if exceptions work, the program just stops and does not reach ca...
- Timo Sintonen (14/35) Jan 01 2014 I do not have my own code here. I just add those files that are
- Timo Sintonen (5/5) Jan 01 2014 I have fond one thing that confuses me. I have defined
- Timo Sintonen (26/31) Jan 05 2014 I think that this code in gcc/deh.d line 105 may not get it right
- Johannes Pfau (8/50) Jan 05 2014 I should really start pushing my local ARM changes upstream. Here's a
- Timo Sintonen (4/13) Jan 05 2014 Meanwhile I got it to pass with this:
- Timo Sintonen (19/32) Jan 08 2014 Exceptions still not working. The code call the unwind routine in
- Iain Buclaw (20/40) Jan 08 2014 Hmm, could maybe try some alignment test:
- Johannes Pfau (6/45) Jan 08 2014 Stupid question, but are C++ exceptions working for you? I think we
- Timo Sintonen (4/11) Jan 08 2014 I have never used c++ in this platform and I do not know what it
- Mike (156/169) Jan 08 2014 I use C++ exceptions on an STM32F4 (ARM Cortex-M4F) with the GNU
- Timo Sintonen (8/18) Feb 28 2014 I investigated this a little. It seems that the processor gets a
- Mike (3/24) Feb 28 2014 blx can also take a label. Are you sure it's an address and not
- Timo Sintonen (8/34) Feb 28 2014 According to the instruction card
- Mike (20/39) Feb 28 2014 It is my understanding that Thumb is 16-bit only, but Thumb-2 is
- Timo Sintonen (12/55) Mar 01 2014 Here, (chapter 1.1)
- Mike (3/10) Mar 01 2014 Well, I yield then to the compiler folks. Hopefully Iain or
- Johannes Pfau (23/34) Mar 01 2014 AFAIK the call to _Unwind_RaiseException [1] is just a normal
- Timo Sintonen (8/43) Mar 01 2014 I checked my code and the library code and there is no other call
- Johannes Pfau (20/27) Mar 01 2014 It's not marked as noreturn though, neither in C nor in the D
- Timo Sintonen (28/39) Mar 02 2014 I read somewhere that -march is ignored when the more specific
- Johannes Pfau (26/77) Mar 02 2014 OK, but at least for the initial problem the question is how did you
- Timo Sintonen (22/48) Mar 02 2014 Gcc build fails with these. It will take time to check them one
- Johannes Pfau (30/57) Mar 07 2014 Multilib is indeed special. AFAIK it's not possible to change multilib
- Timo Sintonen (28/55) Mar 08 2014 It seems that the gcc compilation fails with any of these. These
- Timo Sintonen (21/21) Mar 08 2014 Now I got the exceptions to work.
- Mike (5/6) Mar 09 2014 Nice Work! Congratulations!
- Johannes Pfau (21/35) Mar 09 2014 Great!
- Johannes Pfau (12/24) Jan 01 2014 They work just as well on ARM/linux/glibc as on x86/glibc/linux.
I started to update minlibd with gdc head from last saturday. While testing if exceptions work, the program just stops and does not reach catch or abort. Before investigating further, I want to ask the status of arm exceptions: are they known to work, known not to work or is the status just unknown? Does anybody know if there are any good articles of exceptions and unwinding in gcc or in general?
Jan 01 2014
On 1 Jan 2014 14:05, "Timo Sintonen" <t.sintonen luukku.com> wrote:I started to update minlibd with gdc head from last saturday. Whiletesting if exceptions work, the program just stops and does not reach catch or abort.Before investigating further, I want to ask the status of arm exceptions:are they known to work, known not to work or is the status just unknown?Does anybody know if there are any good articles of exceptions andunwinding in gcc or in general?How are exceptions implemented in minilibd? I assume that you don't use/copy from the gdc compiler runtime folders (rt.* and gcc.*)
Jan 01 2014
On Wednesday, 1 January 2014 at 15:19:01 UTC, Iain Buclaw wrote:On 1 Jan 2014 14:05, "Timo Sintonen" <t.sintonen luukku.com> wrote:I do not have my own code here. I just add those files that are needed to link the test program. Currently I have rt/deh.d, gcc/deh.d, gcc/unwind/pe.d, gcc/unwind/arm.d and core/exception.d Meanwhile I found an exception abi documentation from arm: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf and now I know a little how this is supposed to work. By looking the asm I think that at the throw point it generates the exception object and then the unwind_control_block struct and then calls _Unwind_Resume. The unwind tables have already been in linker script. Then the unwind system should at some point call the personality functions in gcc/deh.d. Maybe I have to check if there is meaningful data in the unwind tables and if the personality functions ever get called.I started to update minlibd with gdc head from last saturday. Whiletesting if exceptions work, the program just stops and does not reach catch or abort.Before investigating further, I want to ask the status of arm exceptions:are they known to work, known not to work or is the status just unknown?Does anybody know if there are any good articles of exceptions andunwinding in gcc or in general?How are exceptions implemented in minilibd? I assume that you don't use/copy from the gdc compiler runtime folders (rt.* and gcc.*)
Jan 01 2014
I have fond one thing that confuses me. I have defined ARM_EABI_UNWINDER but gcc/deh.d has checks for GNU_ARM_EABI_Unwinder. Is this what I should have? When using this I get an error in line 116: static assert ( 8 == 4 ) is false.
Jan 01 2014
On Thursday, 2 January 2014 at 06:54:18 UTC, Timo Sintonen wrote:I have fond one thing that confuses me. I have defined ARM_EABI_UNWINDER but gcc/deh.d has checks for GNU_ARM_EABI_Unwinder. Is this what I should have? When using this I get an error in line 116: static assert ( 8 == 4 ) is false.I think that this code in gcc/deh.d line 105 may not get it right // To place 'obj' behing unwindHeader. enum UNWIND_PAD = (Phase1Info.sizeof + Object.sizeof) % _Unwind_Exception.alignof; static if (UNWIND_PAD > 0) byte[UNWIND_PAD] _pad; Object obj; // The exception object must be directly behind unwindHeader. // (See build_exception_object.) static assert(unwindHeader.offsetof - obj.offsetof == obj.sizeof); // The generic exception header _Unwind_Exception unwindHeader; Its purpose seems to add padding so that obj is aligned at the end of align block just before unwindHeader. Fitst, if I uderstand correct, the amount to pad should be align - modulo, not modulo. The current code happens to work anyway if align is 8 and modulo is 0 or 4 which is usually the case. Second, When I define GNU_ARM_EABI_Unwinder, the assertion fails. Nothing changes in calculation of UNWIND_PAD but the alignment is not correct and the assert fails. With this define the whole size of struct if 96 bytes and 40 bytes without. Something is aligned differently such a way that this calculation cannot find it. I can not print offsetof with pragma msg so I do not know what happens.
Jan 05 2014
Am Sun, 05 Jan 2014 08:26:16 +0000 schrieb "Timo Sintonen" <t.sintonen luukku.com>:On Thursday, 2 January 2014 at 06:54:18 UTC, Timo Sintonen wrote:I should really start pushing my local ARM changes upstream. Here's a fix for the EABI unwinder: https://github.com/jpf91/GDC/commit/262e432e95cbe31a6764cd337f64022a56011eda IIRC I also thought the code in gcc/deh.d wasn't correct. As it wouldn't work for the eabi unwinder anyway (no Phase1Info member) I didn't investigate that though.I have fond one thing that confuses me. I have defined ARM_EABI_UNWINDER but gcc/deh.d has checks for GNU_ARM_EABI_Unwinder. Is this what I should have? When using this I get an error in line 116: static assert ( 8 == 4 ) is false.I think that this code in gcc/deh.d line 105 may not get it right // To place 'obj' behing unwindHeader. enum UNWIND_PAD = (Phase1Info.sizeof + Object.sizeof) % _Unwind_Exception.alignof; static if (UNWIND_PAD > 0) byte[UNWIND_PAD] _pad; Object obj; // The exception object must be directly behind unwindHeader. // (See build_exception_object.) static assert(unwindHeader.offsetof - obj.offsetof == obj.sizeof); // The generic exception header _Unwind_Exception unwindHeader; Its purpose seems to add padding so that obj is aligned at the end of align block just before unwindHeader. Fitst, if I uderstand correct, the amount to pad should be align - modulo, not modulo. The current code happens to work anyway if align is 8 and modulo is 0 or 4 which is usually the case. Second, When I define GNU_ARM_EABI_Unwinder, the assertion fails. Nothing changes in calculation of UNWIND_PAD but the alignment is not correct and the assert fails. With this define the whole size of struct if 96 bytes and 40 bytes without. Something is aligned differently such a way that this calculation cannot find it. I can not print offsetof with pragma msg so I do not know what happens.
Jan 05 2014
On Sunday, 5 January 2014 at 10:06:48 UTC, Johannes Pfau wrote:I should really start pushing my local ARM changes upstream. Here's a fix for the EABI unwinder: https://github.com/jpf91/GDC/commit/262e432e95cbe31a6764cd337f64022a56011eda IIRC I also thought the code in gcc/deh.d wasn't correct. As it wouldn't work for the eabi unwinder anyway (no Phase1Info member) I didn't investigate that though.Meanwhile I got it to pass with this: align(8) int _pad; Exceptions still not working, but this is a start
Jan 05 2014
On Sunday, 5 January 2014 at 10:21:36 UTC, Timo Sintonen wrote:On Sunday, 5 January 2014 at 10:06:48 UTC, Johannes Pfau wrote:Exceptions still not working. The code call the unwind routine in libgcc but that never calls back to personality routine. Neither it resumes to the error callback nor abort. There are several addresses in tables like the call to cleanup code and jump to the catch routine. Are they called in libgcc side or in personality routine? I was just wondering if thumb mode has been taken into account. Cortex processors have only the 16 bit 'thumb' instruction set. This is indicated by setting the lsb of the address to 1 in any address that is used in jumps or calls or any address loads to pc. If the lsb is 0 it will result to illegal instruction fault in Cortex. When compiling with -mthumb the compiler always sets this bit for any address and there is a separate libgcc for thumb mode. When calculating address offsets from exception tables the compiler can not know they are used as jump addresses. It may be possible that callback functions are called in wrong mode. Any thoughts?I should really start pushing my local ARM changes upstream. Here's a fix for the EABI unwinder: https://github.com/jpf91/GDC/commit/262e432e95cbe31a6764cd337f64022a56011eda IIRC I also thought the code in gcc/deh.d wasn't correct. As it wouldn't work for the eabi unwinder anyway (no Phase1Info member) I didn't investigate that though.Meanwhile I got it to pass with this: align(8) int _pad;
Jan 08 2014
On 8 January 2014 08:37, Timo Sintonen <t.sintonen luukku.com> wrote:On Sunday, 5 January 2014 at 10:21:36 UTC, Timo Sintonen wrote:Hmm, could maybe try some alignment test: struct test { byte space; byte[0] end; } struct OurUnwindException { ... enum UNWIND_PAD = (Object.sizeof < test.sizeof) ? test.sizeof - Object.sizeof : 0; byte[UNWIND_PAD] _pad; Object obj; ... } Will have to take a relook at the unwind code again sometime incase there has been changes since it was last updated. Regards IainOn Sunday, 5 January 2014 at 10:06:48 UTC, Johannes Pfau wrote:Exceptions still not working. The code call the unwind routine in libgcc but that never calls back to personality routine. Neither it resumes to the error callback nor abort.I should really start pushing my local ARM changes upstream. Here's a fix for the EABI unwinder: https://github.com/jpf91/GDC/commit/262e432e95cbe31a6764cd337f64022a56011eda IIRC I also thought the code in gcc/deh.d wasn't correct. As it wouldn't work for the eabi unwinder anyway (no Phase1Info member) I didn't investigate that though.Meanwhile I got it to pass with this: align(8) int _pad;
Jan 08 2014
Am Wed, 08 Jan 2014 08:37:43 +0000 schrieb "Timo Sintonen" <t.sintonen luukku.com>:On Sunday, 5 January 2014 at 10:21:36 UTC, Timo Sintonen wrote:Stupid question, but are C++ exceptions working for you? I think we don't change anything inthe compiler related to exception handling, so if C++ worked and D didn't it could only be a problem with the runtime code?On Sunday, 5 January 2014 at 10:06:48 UTC, Johannes Pfau wrote:Exceptions still not working. The code call the unwind routine in libgcc but that never calls back to personality routine. Neither it resumes to the error callback nor abort. There are several addresses in tables like the call to cleanup code and jump to the catch routine. Are they called in libgcc side or in personality routine? I was just wondering if thumb mode has been taken into account. Cortex processors have only the 16 bit 'thumb' instruction set. This is indicated by setting the lsb of the address to 1 in any address that is used in jumps or calls or any address loads to pc. If the lsb is 0 it will result to illegal instruction fault in Cortex. When compiling with -mthumb the compiler always sets this bit for any address and there is a separate libgcc for thumb mode. When calculating address offsets from exception tables the compiler can not know they are used as jump addresses. It may be possible that callback functions are called in wrong mode. Any thoughts?I should really start pushing my local ARM changes upstream. Here's a fix for the EABI unwinder: https://github.com/jpf91/GDC/commit/262e432e95cbe31a6764cd337f64022a56011eda IIRC I also thought the code in gcc/deh.d wasn't correct. As it wouldn't work for the eabi unwinder anyway (no Phase1Info member) I didn't investigate that though.Meanwhile I got it to pass with this: align(8) int _pad;
Jan 08 2014
On Wednesday, 8 January 2014 at 15:52:25 UTC, Johannes Pfau wrote:Stupid question, but are C++ exceptions working for you? I think we don't change anything inthe compiler related to exception handling, so if C++ worked and D didn't it could only be a problem with the runtime code?I have never used c++ in this platform and I do not know what it would require. Some commercial toolsets use gcc as backend but I do not know if they have c++.
Jan 08 2014
On Wednesday, 8 January 2014 at 19:13:36 UTC, Timo Sintonen wrote:On Wednesday, 8 January 2014 at 15:52:25 UTC, Johannes Pfau wrote:I use C++ exceptions on an STM32F4 (ARM Cortex-M4F) with the GNU Tools for ARM Embedded Processors (https://launchpad.net/gcc-arm-embedded). To get it to work, however, I had to make changes to my linker script. Here's the linker script I'm currently using: /******************************************************* Memory Spaces Definitions *********************************************************/ MEMORY { CCRAM (rxw) : ORIGIN = 0x10000000, LENGTH = 64k RAM (rxw) : ORIGIN = 0x20000000, LENGTH = 128k FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024k } /****************************************************** higher address of the user mode stack *********************************************************/ _estack = ORIGIN(CCRAM) + LENGTH(CCRAM); /******************************************************** Section Definitions **********************************************************/ SECTIONS { .ccm (NOLOAD) : { . = ALIGN(4); *(.ccm) . = ALIGN(4); } >CCRAM .isr_vector : /* for Cortex devices, the beginning of the startup code is stored in the .isr_vector section, which goes to FLASH */ { . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ . = ALIGN(4); } >FLASH .text : /* the program code is stored in the .text section, which goes to Flash */ { . = ALIGN(4); *(.text) /* remaining code */ *(.text.*) /* remaining code */ *(.rodata) /* read-only data (constants) */ *(.rodata*) *(.glue_7) *(.glue_7t) *(.eh_frame) /* C++ Exception Handling */ . = ALIGN(4); /* now make sure we keep the C++ constructors */ KEEP (*(.init)) . = ALIGN(4); KEEP (*(.fini)) . = ALIGN(4); __preinit_array_start = .; KEEP (*(.preinit_array)) __preinit_array_end = .; . = ALIGN(4); __init_array_start = .; KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) __init_array_end = .; . = ALIGN(4); __fini_array_start = .; KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) __fini_array_end = .; . = ALIGN(0x4); KEEP (*crtbegin.o(.ctors)) KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*crtend.o(.ctors)) . = ALIGN(0x4); KEEP (*crtbegin.o(.dtors)) KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) KEEP (*(SORT(.dtors.*))) KEEP (*crtend.o(.dtors)) . = ALIGN(4); _etext = .; } >FLASH .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH .ARM : { __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; } >FLASH _sidata = .; /* This is used by the startup in order to initialize the .data secion */ /****************************************************** This is the initialized data section. It is one task of the startup to copy the initial values from FLASH to RAM. ******************************************************/ .data : AT ( _sidata ) { . = ALIGN(4); _sdata = . ; /* This is used by the startup in order to initialize the .data secion */ _data = . ; *(.data) *(.data.*) *(.RAMtext) . = ALIGN(4); _edata = . ; /* This is used by the startup in order to initialize the .data secion */ } >RAM _eidata = _sidata + (_edata - _sdata); /*calculate end address of idata*/ _lastdataromaddress = ORIGIN(FLASH) + LENGTH(FLASH); /*check that idata remains in FLASH region*/ ___toobig___ = ( _eidata > _lastdataromaddress) ? 1 : 0 ; ___toobigmsg___ = ( ___toobig___ ) ? "!!!!!!!!! FLASH IS FULL !!!!!!!!!" : 0 ; /***************************************************** This is the uninitialized data section **********************************************/ .bss : { . = ALIGN(4); _sbss = .; /* This is used by the startup in order to initialize the .bss secion */ _bss = .; *(.bss) *(.bss*) *(COMMON) . = ALIGN(4); _ebss = . ; /* This is used by the startup in order to initialize the .bss secion */ } >RAM PROVIDE ( end = _ebss ); PROVIDE ( _end = _ebss ); /************************************************************ Discard debug info ******************************************************/ /DISCARD/ : { libc.a ( * ) libm.a ( * ) libgcc.a ( * ) libstdc++.a ( * ) libsupc++.a ( * ) } .ARM.attributes 0 : { *(.ARM.attributes) } }Stupid question, but are C++ exceptions working for you? I think we don't change anything inthe compiler related to exception handling, so if C++ worked and D didn't it could only be a problem with the runtime code?I have never used c++ in this platform and I do not know what it would require. Some commercial toolsets use gcc as backend but I do not know if they have c++.
Jan 08 2014
On Wednesday, 8 January 2014 at 19:13:36 UTC, Timo Sintonen wrote:On Wednesday, 8 January 2014 at 15:52:25 UTC, Johannes Pfau wrote:I investigated this a little. It seems that the processor gets a fault interrupt when calling _Unwind_RaiseException in _d_throw. The status bits indicate an invalid instruction code. When looking at the disassembly I see that the call is a blx instruction with address. In Cortex-m4 blx can only take a register argument. Is this a bug in gdc or gcc?Stupid question, but are C++ exceptions working for you? I think we don't change anything inthe compiler related to exception handling, so if C++ worked and D didn't it could only be a problem with the runtime code?
Feb 28 2014
On Friday, 28 February 2014 at 21:18:05 UTC, Timo Sintonen wrote:On Wednesday, 8 January 2014 at 19:13:36 UTC, Timo Sintonen wrote:blx can also take a label. Are you sure it's an address and not a label?On Wednesday, 8 January 2014 at 15:52:25 UTC, Johannes Pfau wrote:I investigated this a little. It seems that the processor gets a fault interrupt when calling _Unwind_RaiseException in _d_throw. The status bits indicate an invalid instruction code. When looking at the disassembly I see that the call is a blx instruction with address. In Cortex-m4 blx can only take a register argument. Is this a bug in gdc or gcc?Stupid question, but are C++ exceptions working for you? I think we don't change anything inthe compiler related to exception handling, so if C++ worked and D didn't it could only be a problem with the runtime code?
Feb 28 2014
On Saturday, 1 March 2014 at 02:59:37 UTC, Mike wrote:On Friday, 28 February 2014 at 21:18:05 UTC, Timo Sintonen wrote:According to the instruction card http://infocenter.arm.com/help/topic/com.arm.doc.qrc0006e/QRC0006_UAL16.pdf blx with label is valid in thumb instruction set. But it is a 32 bit instruction so I think it does not exist in any thumb only processors. Here we can see it is not valid in M4: http://infocenter.arm.com/help/topic/com.arm.doc.dui0553a/BABEFHAE.htmlOn Wednesday, 8 January 2014 at 19:13:36 UTC, Timo Sintonen wrote:blx can also take a label. Are you sure it's an address and not a label?On Wednesday, 8 January 2014 at 15:52:25 UTC, Johannes Pfau wrote:I investigated this a little. It seems that the processor gets a fault interrupt when calling _Unwind_RaiseException in _d_throw. The status bits indicate an invalid instruction code. When looking at the disassembly I see that the call is a blx instruction with address. In Cortex-m4 blx can only take a register argument. Is this a bug in gdc or gcc?Stupid question, but are C++ exceptions working for you? I think we don't change anything inthe compiler related to exception handling, so if C++ worked and D didn't it could only be a problem with the runtime code?
Feb 28 2014
On Saturday, 1 March 2014 at 07:26:16 UTC, Timo Sintonen wrote:It is my understanding that Thumb is 16-bit only, but Thumb-2 is a mix of 16 and 32-bit instructions (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0471c/CHDFEDDB.html). Under the "Specifications" tab of this site (http://www.arm.com/products/processors/cortex-m/cortex-m4-processor.php) it shows the Cortex-M4 as a Thumb-2 capable core. I don't know how to tell GDC/GCC to only generate Thumb-1 as opposed to Thumb-2 so it's my assumption it will default the latest Thumb based on the specified arch or cpu argument. In that case, I think it will generate Thumb-2 instructions. Correct me if I'm wrong. Here's the instruction card for Thumb-2 (http://infocenter.arm.com/help/topic/com.arm.doc.qrc0001l/QRC0001_UAL.pdf). It shows the blx <label> instruction is valid for 5T and later architectures. The Cortex-M4 is ARMv7EM architecture, so I think it should be good to go. However, your second think doesn't show the blx {label} syntax, so I'm a little confused. Can you post the assembly code?According to the instruction card http://infocenter.arm.com/help/topic/com.arm.doc.qrc0006e/QRC0006_UAL16.pdf blx with label is valid in thumb instruction set. But it is a 32 bit instruction so I think it does not exist in any thumb only processors. Here we can see it is not valid in M4: http://infocenter.arm.com/help/topic/com.arm.doc.dui0553a/BABEFHAE.htmlI investigated this a little. It seems that the processor gets a fault interrupt when calling _Unwind_RaiseException in _d_throw. The status bits indicate an invalid instruction code. When looking at the disassembly I see that the call is a blx instruction with address. In Cortex-m4 blx can only take a register argument. Is this a bug in gdc or gcc?blx can also take a label. Are you sure it's an address and not a label?
Feb 28 2014
On Saturday, 1 March 2014 at 07:53:45 UTC, Mike wrote:On Saturday, 1 March 2014 at 07:26:16 UTC, Timo Sintonen wrote:Here, (chapter 1.1) http://infocenter.arm.com/help/topic/com.arm.doc.dui0553a/DUI0553A_cortex_m4_dgug.pdf "The Cortex-M4 implements a __version__ of the thumb instruction set __based__ on thumb2." So it is thumb2 but maybe a little modified. There is nothing interesting in the assembly, only this wrong call. This form of instruction is just missing in M4 and it gives an invalid instruction fault. So what are we arguing about? If this is so hard for us to find, no wonder the compiler writers have not noticed this.It is my understanding that Thumb is 16-bit only, but Thumb-2 is a mix of 16 and 32-bit instructions (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0471c/CHDFEDDB.html). Under the "Specifications" tab of this site (http://www.arm.com/products/processors/cortex-m/cortex-m4-processor.php) it shows the Cortex-M4 as a Thumb-2 capable core. I don't know how to tell GDC/GCC to only generate Thumb-1 as opposed to Thumb-2 so it's my assumption it will default the latest Thumb based on the specified arch or cpu argument. In that case, I think it will generate Thumb-2 instructions. Correct me if I'm wrong. Here's the instruction card for Thumb-2 (http://infocenter.arm.com/help/topic/com.arm.doc.qrc0001l/QRC0001_UAL.pdf). It shows the blx <label> instruction is valid for 5T and later architectures. The Cortex-M4 is ARMv7EM architecture, so I think it should be good to go. However, your second think doesn't show the blx {label} syntax, so I'm a little confused. Can you post the assembly code?According to the instruction card http://infocenter.arm.com/help/topic/com.arm.doc.qrc0006e/QRC0006_UAL16.pdf blx with label is valid in thumb instruction set. But it is a 32 bit instruction so I think it does not exist in any thumb only processors. Here we can see it is not valid in M4: http://infocenter.arm.com/help/topic/com.arm.doc.dui0553a/BABEFHAE.htmlI investigated this a little. It seems that the processor gets a fault interrupt when calling _Unwind_RaiseException in _d_throw. The status bits indicate an invalid instruction code. When looking at the disassembly I see that the call is a blx instruction with address. In Cortex-m4 blx can only take a register argument. Is this a bug in gdc or gcc?blx can also take a label. Are you sure it's an address and not a label?
Mar 01 2014
On Saturday, 1 March 2014 at 08:56:26 UTC, Timo Sintonen wrote:There is nothing interesting in the assembly, only this wrong call. This form of instruction is just missing in M4 and it gives an invalid instruction fault. So what are we arguing about? If this is so hard for us to find, no wonder the compiler writers have not noticed this.Well, I yield then to the compiler folks. Hopefully Iain or Johannes can provide some insight.
Mar 01 2014
On Saturday, 1 March 2014 at 09:24:40 UTC, Mike wrote:On Saturday, 1 March 2014 at 08:56:26 UTC, Timo Sintonen wrote:AFAIK the call to _Unwind_RaiseException [1] is just a normal function call [2] to a extern(C) function in a different compilation unit. It's not even a builtin so it doesn't look like a gdc bug. GCC bug is more likely but I wonder what exactly makes this case special? Why does this not happen for every function call to a extern(C) function? Please try the following: * Verify your --with-cpu, --with-arch, --with-tune flags for gcc configure. Also make sure that binutils is configured with the correct flags. * Have a look at the build log how gcc/deh.d is compiled. Use the same compile command, but generate assembly via -S. Then look at the asm code to check whether the compiler or the assembler/linker is to blame. * Try to reduce the example / understand why exactly this happens only in this case. * When you have a reduced example, try to port it to C and see if GCC handles it correctly. [1] https://github.com/D-Programming-GDC/GDC/blob/master/libphobos/libdruntime/gcc/deh.d#L151 [2] https://github.com/D-Programming-GDC/GDC/blob/master/libphobos/libdruntime/gcc/unwind/arm.d#L191There is nothing interesting in the assembly, only this wrong call. This form of instruction is just missing in M4 and it gives an invalid instruction fault. So what are we arguing about? If this is so hard for us to find, no wonder the compiler writers have not noticed this.Well, I yield then to the compiler folks. Hopefully Iain or Johannes can provide some insight.
Mar 01 2014
On Saturday, 1 March 2014 at 10:49:57 UTC, Johannes Pfau wrote:On Saturday, 1 March 2014 at 09:24:40 UTC, Mike wrote:I checked my code and the library code and there is no other call like this. I think there is one thing that makes this function special: if I understand correct, this function will not return. If there is some noreturn attribute somewhere this function might be handled in a different way. Is it so that gdc does not generate any assembly directly? So this would be a bug in gcc side and I may report it there.On Saturday, 1 March 2014 at 08:56:26 UTC, Timo Sintonen wrote:AFAIK the call to _Unwind_RaiseException [1] is just a normal function call [2] to a extern(C) function in a different compilation unit. It's not even a builtin so it doesn't look like a gdc bug. GCC bug is more likely but I wonder what exactly makes this case special? Why does this not happen for every function call to a extern(C) function? Please try the following: * Verify your --with-cpu, --with-arch, --with-tune flags for gcc configure. Also make sure that binutils is configured with the correct flags. * Have a look at the build log how gcc/deh.d is compiled. Use the same compile command, but generate assembly via -S. Then look at the asm code to check whether the compiler or the assembler/linker is to blame. * Try to reduce the example / understand why exactly this happens only in this case. * When you have a reduced example, try to port it to C and see if GCC handles it correctly. [1] https://github.com/D-Programming-GDC/GDC/blob/master/libphobos/libdruntime/gcc/deh.d#L151 [2] https://github.com/D-Programming-GDC/GDC/blob/master/libphobos/libdruntime/gcc/unwind/arm.d#L191There is nothing interesting in the assembly, only this wrong call. This form of instruction is just missing in M4 and it gives an invalid instruction fault. So what are we arguing about? If this is so hard for us to find, no wonder the compiler writers have not noticed this.Well, I yield then to the compiler folks. Hopefully Iain or Johannes can provide some insight.
Mar 01 2014
On Saturday, 1 March 2014 at 11:46:03 UTC, Timo Sintonen wrote:I checked my code and the library code and there is no other call like this. I think there is one thing that makes this function special: if I understand correct, this function will not return. If there is some noreturn attribute somewhere this function might be handled in a different way. Is it so that gdc does not generate any assembly directly? So this would be a bug in gcc side and I may report it there.It's not marked as noreturn though, neither in C nor in the D code. The function can return if there is some kind of error (http://refspecs.linuxfoundation.org/LSB_3.1.0/LSB-Core-S390/LSB-Core-S390/baselib--unwind-raiseexception.html) Some google-fu shows that someone reported this bug here: http://gcc.gnu.org/ml/gcc-help/2013-06/msg00091.html https://sourceware.org/bugzilla/show_bug.cgi?id=15628 However, someone also had this problem on this german site: http://www.mikrocontroller.net/topic/312956 and the solution was that -mcpu alone was not good enough, he had to specify -march flags as well so please double-check your flags. It's possible that binutils doesn't work properly with -mcpu so I'd do this: -march=armv7e-m -mcpu=cortex-m4 -mthumb -mtune=cortex-m4 Or better at configure time: --with-arch=armv7e-m --with-cpu=cortex-m4 --with-mode=thumb --with-tune=cortex-m4 Oh, and if that works: Please add a comment tu the bintuils issue that specifying -march helps.
Mar 01 2014
On Saturday, 1 March 2014 at 12:53:14 UTC, Johannes Pfau wrote:However, someone also had this problem on this german site: http://www.mikrocontroller.net/topic/312956 and the solution was that -mcpu alone was not good enough, he had to specify -march flags as well so please double-check your flags. It's possible that binutils doesn't work properly with -mcpu so I'd do this: -march=armv7e-m -mcpu=cortex-m4 -mthumb -mtune=cortex-m4 Or better at configure time: --with-arch=armv7e-m --with-cpu=cortex-m4 --with-mode=thumb --with-tune=cortex-m4I read somewhere that -march is ignored when the more specific -mcpu is present. On the other hand, ld has no cpu option, only --architecture. That did not have any effect. A little background: I have the main makefile and all definitions in toplevel directory. Libraries and projects are in subdirs. Any subdir makefile includes settings from topdir. In topdir I just give export projectdir=xxx and then run make. Any project in any language is run from the same makefile with the same settings. I use separate compiling and pass myself options to gcc, as and ld. A reduced version of this toolset is in the minlibd repo in tools directory. I decided to rebuild all my apps and libs. Now I have lots of blx instructions in my code. So this is not related to exceptions. I just triggered this when playing with deh.d. I have not been able to confirm this, but this may be something like when linking libraries that have unresolved symbols. If the symbol is already available, the call is bl, but if the symbol will be resolved from a later library, the call will be blx. Libgcc is always the last so any call to its functions will be blx. When I compile my c only project, I will not get these calls. I have compared the object list files but I can not find any meaningful difference. Could it be possible that gdc generated asm files have some attribute/directive/segment name/whatever that changes the behavior in ld. Obviously there are more segments in d executable, like unwind and debug info. What is the thing that makes it different for ld?
Mar 02 2014
Am Sun, 02 Mar 2014 11:20:53 +0000 schrieb "Timo Sintonen" <t.sintonen luukku.com>:On Saturday, 1 March 2014 at 12:53:14 UTC, Johannes Pfau wrote:OK, but at least for the initial problem the question is how did you build _libgcc_. I guess it was build as part of the normal gcc ./configure & make & make install process. To make sure that libgcc is built correctly for Cortex-M4 you have to specify "--with-arch=armv7e-m --with-cpu=cortex-m4 --with-mode=thumb --with-tune=" when configuring gcc/gdc. (And I don't see these flags mentioned in https://bitbucket.org/timosi/minlibd/src/691c76aa2b543998bb573e6ce6d96951a80817bd/README.gdc?at=default)However, someone also had this problem on this german site: http://www.mikrocontroller.net/topic/312956 and the solution was that -mcpu alone was not good enough, he had to specify -march flags as well so please double-check your flags. It's possible that binutils doesn't work properly with -mcpu so I'd do this: -march=armv7e-m -mcpu=cortex-m4 -mthumb -mtune=cortex-m4 Or better at configure time: --with-arch=armv7e-m --with-cpu=cortex-m4 --with-mode=thumb --with-tune=cortex-m4I read somewhere that -march is ignored when the more specific -mcpu is present. On the other hand, ld has no cpu option, only --architecture. That did not have any effect. A little background: I have the main makefile and all definitions in toplevel directory. Libraries and projects are in subdirs. Any subdir makefile includes settings from topdir. In topdir I just give export projectdir=xxx and then run make. Any project in any language is run from the same makefile with the same settings. I use separate compiling and pass myself options to gcc, as and ld. A reduced version of this toolset is in the minlibd repo in tools directory.I decided to rebuild all my apps and libs. Now I have lots of blx instructions in my code. So this is not related to exceptions. I just triggered this when playing with deh.d. I have not been able to confirm this, but this may be something like when linking libraries that have unresolved symbols. If the symbol is already available, the call is bl, but if the symbol will be resolved from a later library, the call will be blx. Libgcc is always the last so any call to its functions will be blx.Sounds strange, I don't think we could cause this in the gdc frontend. I guess binutils generates blx if thumb code calls arm code or the other way round. So I'd verify which libraries are really picked up by ld (ld --verbose) then check if the entry points are in thumb or arm mode: http://stackoverflow.com/a/15931232 This sounds a lot as if calls to the same library/object file generate bl instructions as the code is in the same mode, but functions in external libraries are in a different mode and therefore generate blx.When I compile my c only project, I will not get these calls. I have compared the object list files but I can not find any meaningful difference. Could it be possible that gdc generated asm files have some attribute/directive/segment name/whatever that changes the behavior in ld. Obviously there are more segments in d executable, like unwind and debug info. What is the thing that makes it different for ld?I'm not sure but I still don't think we could cause this. This low-level stuff is usually part of the backend, the frontend doesn't know much about thumb/arm. Did you use the same gcc which was compiled with your gdc or did you use a gcc from a different toolchain? In either case I probably need a reduced test case, otherwise I'm just guessing here ;-)
Mar 02 2014
On Sunday, 2 March 2014 at 15:36:01 UTC, Johannes Pfau wrote:To make sure that libgcc is built correctly for Cortex-M4 you have to specify "--with-arch=armv7e-m --with-cpu=cortex-m4 --with-mode=thumb --with-tune=" when configuring gcc/gdc. (And I don't see these flags mentioned in https://bitbucket.org/timosi/minlibd/src/691c76aa2b543998bb573e6ce6d96951a80817bd/README.gdc?at=default)Gcc build fails with these. It will take time to check them one by one. Also enable/disable-multilib may affect to this. Then I updated my host binutils and gcc to latest head and with these I compiled cross binutils and gcc/gdc from head. I used my current settings. Now my own code and minlibd do not have any blx instructions but libgcc has some.Sounds strange, I don't think we could cause this in the gdc frontend.I am not saying it is a gdc bug. It may very well be a side effect of a flag that is related to maybe umwinding or relocation. I do have two kind of object files now in my executable and I just like to know what is the difference between them.I guess binutils generates blx if thumb code calls arm code or the other way round. So I'd verify which libraries are really picked up by ld (ld --verbose) then check if the entry points are in thumb or arm mode: http://stackoverflow.com/a/15931232 This sounds a lot as if calls to the same library/object file generate bl instructions as the code is in the same mode, but functions in external libraries are in a different mode and therefore generate blx.Yes, I think blx is for this. M4 does not have arm mode and there is no this instruction, so it should be a linker error if the user try to mix objects with different modes. As I mentioned, I pass manually everything, including libgcc. Nothing is picked by default. The multilib thing should be just because of this. There are 4 variants of libgcc. If I pick the m4-fpu library it should be already compiled with the right flags. If it is not, I think that is a gcc bug. How can I check from the library which modes/flags is has?I'm not sure but I still don't think we could cause this. This low-level stuff is usually part of the backend, the frontend doesn't know much about thumb/arm.Yes, this is going a little off-topic now
Mar 02 2014
Am Sun, 02 Mar 2014 18:33:00 +0000 schrieb "Timo Sintonen" <t.sintonen luukku.com>:On Sunday, 2 March 2014 at 15:36:01 UTC, Johannes Pfau wrote:Multilib is indeed special. AFAIK it's not possible to change multilib flags without changing some file in gcc (gcc/config/t-arm or something like that).To make sure that libgcc is built correctly for Cortex-M4 you have to specify "--with-arch=armv7e-m --with-cpu=cortex-m4 --with-mode=thumb --with-tune=" when configuring gcc/gdc. (And I don't see these flags mentioned in https://bitbucket.org/timosi/minlibd/src/691c76aa2b543998bb573e6ce6d96951a80817bd/README.gdc?at=default)Gcc build fails with these. It will take time to check them one by one. Also enable/disable-multilib may affect to this.I am not saying it is a gdc bug. It may very well be a side effect of a flag that is related to maybe umwinding or relocation. I do have two kind of object files now in my executable and I just like to know what is the difference between them.I'd like to know the reason as well, but I think I really need a small test case to continue looking into this. Could you upload your toolchain binaries somewhere?You seem to be right that binutils doesn't have an architecture flag and therefore the linker can't even know you're targeting Cortex-M4. http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/IHI0044E_aaelf.pdf 4.5.3 ---------- In addition to the normal rules for symbol values the following rules shall also apply to symbols of type STT_FUNC : If the symbol addresses a Thumb instruction, its value is the address of the instruction with bit zero set (in a relocatable object, the section offset with bit zero set) ---------- However, objdump is 'clever' and removes this bit m( But with readelf: readelf liba.o -s 8: 00000000 28 FUNC GLOBAL DEFAULT 1 test readelf libt.o -s 8: 00000001 18 FUNC GLOBAL DEFAULT 1 test In my simple tests ld does really only use blx for arm->thumb / thumb->arm calls. In all other cases it uses bl. And it's indeed the linker making this decision, the compiler always emits 'bl'. Would be great if you could confirm if it's a linker issue in your case as well.Yes, I think blx is for this. M4 does not have arm mode and there is no this instruction, so it should be a linker error if the user try to mix objects with different modes. As I mentioned, I pass manually everything, including libgcc. Nothing is picked by default. The multilib thing should be just because of this. There are 4 variants of libgcc. If I pick the m4-fpu library it should be already compiled with the right flags. If it is not, I think that is a gcc bug. How can I check from the library which modes/flags is has?
Mar 07 2014
On Friday, 7 March 2014 at 18:41:35 UTC, Johannes Pfau wrote:It seems that the gcc compilation fails with any of these. These flags do set the features of the compiler which in turn have effect to the libraries it builds. These do not set the libgcc build process and I get similar errors than Mike reported a while ago. The reason is that the build process still try to make arm mode libraries even when the compiler is thumb only.To make sure that libgcc is built correctly for Cortex-M4 you have to specify "--with-arch=armv7e-m --with-cpu=cortex-m4 --with-mode=thumb --with-tune=" when configuring gcc/gdc.Gcc build fails with these. It will take time to check them one by one. Also enable/disable-multilib may affect to this.Multilib is indeed special. AFAIK it's not possible to change multilib flags without changing some file in gcc (gcc/config/t-arm or something like that).It has been my plan to investigate the library build process this weekendI'd like to know the reason as well, but I think I really need a small test case to continue looking into this. Could you upload your toolchain binaries somewhere?You seem to be right that binutils doesn't have an architecture flag and therefore the linker can't even know you're targeting Cortex-M4.I was getting different object files from the same sources with different versions of the compiler. I tried to find what was the difference between those files. An oo language naturally makes a little bit different object file than pure c. There was something that made ld think the files are different and needed the interworking call. I just could not find what was the flag or attribute or section that made ld to think so. As I told, then I updated everything to latest head versions and I think I am now where I was before. I do not have the original binaries any more. Binutils 2-23 and gcc/gdc heads between mid of january to mid of february at least caused the problem. There still is some blx instructions but I think they have always been there. I just have not needed those functions before I started with exceptions. The linking process seems to be controlled by those arm attributes. I did not know readelf can also read .o files. It lists attributes and all kind of info much better than objdump. Next I will investigate my files with this and try to find out how to affect to libgcc generation.In my simple tests ld does really only use blx for arm->thumb / thumb->arm calls. In all other cases it uses bl. And it's indeed the linker making this decision, the compiler always emits 'bl'. Would be great if you could confirm if it's a linker issue in your case as well.
Mar 08 2014
Now I got the exceptions to work. I have not been able to find how to control the libgcc build process. The configure script seems not to know that I give different defaults for the compiler in --with switches. Configure still assumes the compiler defaults arm mode although it is in thumb mode. I should also be able to give different default values to all four libraries that are built. I solved this by building with defaults and then hacked the makefile of that libgcc directory I use. (fpu) Then I remade the library. Changing LIBGCC_FLAGS at line 229 did the trick. So exceptions seems to work now. There is one thing: because I do not have gc, the OurUnwindException struct that is allocated in _d_throw is never freed. This is an issue for anybody not using gc, so there should be a general solution. The three problems in this project were: - struct alignment issue that Iain has fixed - a change/bug in gcc in january-february causing different object generation. Seems to be fixed in head now. - building libgcc with the same settings than the rest of the application. I am still looking a way to control the library build process.
Mar 08 2014
On Sunday, 9 March 2014 at 07:57:46 UTC, Timo Sintonen wrote:Now I got the exceptions to work.Nice Work! Congratulations! I read your wiki, but didn't see your source code yet (I assume its coming, yes?). Anyway, thanks for sharing this information. Mike
Mar 09 2014
Am Sun, 09 Mar 2014 07:57:45 +0000 schrieb "Timo Sintonen" <t.sintonen luukku.com>:Now I got the exceptions to work. I have not been able to find how to control the libgcc build process. The configure script seems not to know that I give different defaults for the compiler in --with switches. Configure still assumes the compiler defaults arm mode although it is in thumb mode. I should also be able to give different default values to all four libraries that are built. I solved this by building with defaults and then hacked the makefile of that libgcc directory I use. (fpu) Then I remade the library. Changing LIBGCC_FLAGS at line 229 did the trick. [...]Great! The configure script doesn't really have to know about the "-with-*" flags - these are used by default if you don't pass any arguments to gcc/gdc. However this can't work for your multilib setup. libgcc should really build with the correct multilib flags, so that's strange. You can check the used multilib flags with gcc -print-multi-lib You might have to edit gcc/config/arm/t-arm-elf You could check how the gcc-arm-embedded project modifies that file, IIRC they build special multilibs for cortex m3/m4 (the default gcc configuration only builds thumb/not-thumb*) https://launchpad.net/gcc-arm-embedded http://airs.com/ian/configure/configure_8.html http://gcc.gnu.org/onlinedocs/gccint/Target-Fragment.html * BTW: This can explain invalid instructions in libgcc: it's only build with -mthumb but not with -march in the default multilib configuration.
Mar 09 2014
Am Wed, 01 Jan 2014 14:02:42 +0000 schrieb "Timo Sintonen" <t.sintonen luukku.com>:I started to update minlibd with gdc head from last saturday. While testing if exceptions work, the program just stops and does not reach catch or abort. Before investigating further, I want to ask the status of arm exceptions: are they known to work, known not to work or is the status just unknown?They work just as well on ARM/linux/glibc as on x86/glibc/linux. (Exception chaining isn't working on any architecture, IIRC). There's a problem with nothrow functions on ARM though: GDC currently marks nothrow functions with TREE_NOTHROW. However, if such a functions throws an Error (which is legal in D) the program crashes. The solution is not setting TREE_NOTHROW, see here: https://github.com/jpf91/GDC/commit/935198bda01ada89d946ee28819253cca872bea5Does anybody know if there are any good articles of exceptions and unwinding in gcc or in general?The keywords here are 'dwarf exceptions' and 'sjlj exceptions' (or setjump/longjump exceptions) and you probably want 'dwarf exceptions'. http://gcc.gnu.org/ml/gcc/2002-07/msg00391.html
Jan 01 2014