January 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:
> > 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. 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?

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?
January 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++.
January 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:
>
>>
>> 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++.

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) }
}

February 28, 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:
>
>>
>> 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 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?

March 01, 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:
>> 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 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?
March 01, 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:
>> 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:
>>>
>>>>
>>>> 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 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?

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.html
March 01, 2014
On Saturday, 1 March 2014 at 07:26:16 UTC, Timo Sintonen 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?
>>
>> blx can also take a label.  Are you sure it's an address and not
>> a label?
>
> 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.html

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?
March 01, 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:
>>>> 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?
>>>
>>> blx can also take a label.  Are you sure it's an address and not
>>> a label?
>>
>> 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.html
>
> 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?

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.
March 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.
March 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:
>> 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.

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#L191