gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

C/C++ > Full C++ - with exceptions

#2510 - Raz - Wed Feb 05, 2003 12:42 pm

I am trying to get a test project to work using C++ with exceptions supported. Without wanting to start another C++ v. C debate, I am looking to get a makefile together that will:
a) compile C++ code (done)
b) allow me to use exceptions

The latter eludes me until now, and I haven't been able to find any pointers (google, etc.) on how to make this work.

I have some code that compiles a try|catch arrangement, but on running it in VisualBoyAdvance, it seems to be bombing out.

Code:
int main ()
{
   print ("start\n");
   int i = 0;

   try
   {
      print ("throw\n");
      throw 1;
   }
   catch (...)
   {
      print ("caught\n");
   }
   
   if (i == 1)
   {
      print ("loop == 1\n");
   }
   else
   {
      print ("loop != 1\n");
   }

   while (1);

   return 0;
}


This generates text in the logging window saying

start
throw
start
throw
...
...

Anyone have any ideas....

Cheers,
- raz

#2512 - siaspete - Wed Feb 05, 2003 2:42 pm

Hey Raz,

I get the same thing. Using a simple program that just throws a char*, and tries to catch it, it looks like as soon as execution reaches the "throw", the program resets.

Perhaps G++ is putting nonsense in the stack?

#2516 - col - Wed Feb 05, 2003 4:37 pm

Is gcc trying to switch the cpu from user mode into a privileged mode? - which is not allowed on the gba! (afair anyone?)

Check the generated assembly for writes to bits 0-4 of the CPSR (program status register)

cheers

col

#3218 - Raz - Thu Feb 20, 2003 2:40 pm

Ok, I have tried it some more but to no avail... My ARM/ASM skills are zero, so any help is appreciated in making sense of this. I have the following code and translation in ASM:

Code:
int main ()
{
   try
   {
      throw 1;
   }
   catch (...)
   {
      while (1);
   }
   while (1);

   return 0;
}


This is then translated into the following ASM:

Code:
@ Generated by gcc 3.0.2 (DevKit-Advance) for ARM/elf
   .file   "main.cpp"
   .code   16
   .text
   .align   2
   .global   main
   .thumb_func
   .type   main,function
main:
   push   {r4, r5, r6, r7, lr}
   mov   r7, fp
   mov   r6, sl
   mov   r5, r9
   mov   r4, r8
   push   {r4, r5, r6, r7}
   mov   r7, sp
   sub   sp, sp, #48
   ldr   r3, .L21
   mov   r2, #20
   neg   r2, r2
   str   r3, [r2, r7]
   ldr   r3, .L21+4
   add   r2, r2, #4
   str   r3, [r2, r7]
   mov   r3, #12
   neg   r3, r3
   str   r7, [r3, r7]
   ldr   r3, .L21+8
   add   r2, r2, #8
   str   r3, [r2, r7]
   mov   r3, sp
   sub   r2, r7, #4
   str   r3, [r2]
   mov   r0, r7
   sub   r0, r0, #44
   bl   _Unwind_SjLj_Register
   bl   __gccmain
   mov   r0, #4
   bl   __cxa_allocate_exception
   mov   r3, #1
   str   r3, [r0]
   mov   r2, #48
   neg   r2, r2
   ldr   r2, [r2, r7]
   str   r3, [r2]
   ldr   r1, .L21+12
   mov   r2, #0
   bl   __cxa_throw
.L20:
   
   .code   16
   mov   r3, #36
   neg   r3, r3
   ldr   r0, [r3, r7]
   bl   __cxa_begin_catch
.L6:
   b   .L6
.L22:
   .align   2
.L21:
   .word   __gxx_personality_sj0
   .word   .LLSDA0
   .word   .L20
   .word   _ZTIi
.L1:
.Lfe1:
   .size   main,.Lfe1-main
   .section .gcc_except_table,"aw"
   .align   2
.LLSDA0:
   .byte   0xff
   .byte   0x0
   .byte   0xd
   .byte   0x3
   .byte   0x2
   .byte   0x0
   .byte   0x1
   .byte   0x1
   .byte   0x0
   .align   2
   .word   0

   .text


What does it all mean (short course in ASM probably!). There are all kinds of references to structures and calls that are exception related, but still the behaviour is not as expected. It may run on GBA hardware, because I run all of this in VBA.

Any GBA Gurus about....

- Raz

#3222 - col - Thu Feb 20, 2003 5:14 pm

Raz wrote:
Ok, I have tried it some more but to no avail... My ARM/ASM skills are zero, so any help is appreciated in making sense of this. I have the following code and translation in ASM:
...
- Raz


There aren't any writes to CPSR register in that asm - what about: __cxa_throw
__cxa_begin_catch
etc...

maybe one of those functions is the culprit? - it's just as likely to be nothing to do with this though...

here's another stab in the dark :)
What Linkscript are you using? does it set up the gcc exception table properly?
Or is it the table just being left left un-initialised as zeros - which would explain the resets described by siaspete...


cheers

col.

#3229 - siaspete - Thu Feb 20, 2003 6:50 pm

Hmm, I'm not explicitly using a linkscript, just however DevkitAdvance sets things up. I'll have a mess with it tonight, see if I can do anything about it.

#3464 - Raz - Tue Feb 25, 2003 12:46 pm

Well, I managed to get it to work. Now I'll try to explain what happened but my knowledge isn't very deep. Maybe someone else can supply some details? Using GDB I found it would bail on specific instructions. That got me to start thinking about the whole THUMB/ARM/Interwork thing.

So I tried out different combinations of '-mthumb', etc. settings for the compilation step, the link step and using the specific crtbegin.o and crtend.o files. Presto! During trying the different combinations, it would get further through the code, and at one point GDB reported a SIGILL (illegal instruction). A bit like working blind, as I don't ASM, but I guess you have to start somewhere ;)

Short answer therefore is to start using only '-mthumb-interwork' for compilation and linking, as well as explicitly picking 'crtbegin.o' and 'crtend.o' files from $devkitadv$\lib\gcc-lib\arm-agb-elf\3.0.2\interwork. It will not work with '-mthumb' enabled!

I used to have '-mthumb -mthumb-interwork' as default (copied it from others), no linkscript, no crt0.s, same as siaspete. I am still trying to find out more about it, but for the moment I think it was basically illegal instructions from a clash between ARM and THUMB code.

I use:
    Lnkscript 1.3 (Frohwein)
    crt0.S v1.28 (Frohwein) - .equ __CPPSupport, 1 uncommented
    crtbegin.o/crtend.o - from $devkitadv$\lib\gcc-lib\arm-agb-elf\3.0.2\interwork


Build.bat
Code:
PATH=D:\DevKitAdv\bin

g++ -g -c -Wall -Werror -O1 -mthumb-interwork -o main.o main.cpp 
g++ -g -c -Wall -Werror -O1 -mthumb-interwork -o crt0.o crt0.s

g++ -T lnkscript -nostartfiles -mthumb-interwork -o gba.elf crtbegin.o crtend.o crt0.o main.o -Lstdc++ -Lstdsupc++


main.cpp
Code:
//! print - THUMB code - from Forgotten
//! http://vboy.emuhq.com/
void print(char *s)
{
   asm volatile("mov r0, %0;"
           "swi 0xff;"
      : // no output
      : "r" (s)
      : "r0");
}


//! Main entry point
int main ()
{
   print ("start\n");
   try
   {
      print ("throw\n");
      int i = 1;
      throw i;
   }   
   catch (...)
   {
      print ("catch\n");
      while(1);   
   }

   print("further\n");
   while(1);

   return 0;
}


Well, I am happy that it works. As soon as I understand it better, I will post something more. That will involve some more playing around with it tho...

Thanks guys,

- Raz

#3492 - mbcook - Wed Feb 26, 2003 12:55 am

May I ask why you need exceptions? I was always tought that they were to help you out when you prompt for the user to inter an int and they type "mary" or when you have to load classes on the fly and you need to be able to catch anything, etc. So on a closed system like the GBA where you know what's going to happen, why would you ever need them?

Just wondering. I don't do much programming. While I do know OF exections, I've never used.
_________________
--Michael

#3504 - siaspete - Wed Feb 26, 2003 8:20 am

On a small system like the GBA, memory allocation in particular can fail. "new" should throw an exception on failure, so if it's not supported your app will crash instead of allowing you to catch the exception and put up a sensible error message.

I also find it a much nicer system to use for signalling errors, as opposed to passing return codes around.

#3511 - Raz - Wed Feb 26, 2003 11:41 am

Exceptions allow you to separate normal code from error handling code. siaspete's memory allocation example is quite good. If you want some background, there is a good article at flipcode (http://www.flipcode.com/tutorials/tut_exceptions.shtml). Normally exceptions aren't used on embedded systems or on the GBA, as they increase the size of the executable, etc.

The real reason why I want to use exceptions is that I want to use CppUnit (http://cppunit.sourceforge.net/), a testing framework, to help me develop on the GBA. It isn't really well suited to the GBA, it requires exceptions and streams.

- Raz

#3535 - mbcook - Wed Feb 26, 2003 8:06 pm

Memory problems. DUH. I should have thought of that. Oh well, back to being an idiot for me :)
_________________
--Michael

#5911 - Jason Wilkins - Mon May 12, 2003 7:28 pm

This is an old post, but I would like to take a look a why this did not work. It may very well be that it will work out of the box with DevKit Advance R5.
_________________
http://devkitadv.sourceforge.net

#6308 - MojoJojo - Thu May 22, 2003 6:55 pm

Exceptions can be used for more than just error handling. They allow you to unroll your stack quickly. Which can be used to speed up certain algorithms, and save space, in certain situations.

Although you should probably unroll any algorithm that requires much recursion on the GBA.

#6617 - Jason Wilkins - Fri May 30, 2003 5:01 pm

In my recent investigation into some memory allocation problems with C++, the test program someone sent me used exceptions to catch bad_alloc (thrown by new). It worked perfectly well. So, if you want exceptions to work, they appear to work just fine in DevKit Advance R5.
_________________
http://devkitadv.sourceforge.net