2. Why need exception handling ?
Exceptions provide a way to react to
exceptional circumstances (like runtime
errors)
Transferring control to special functions called
handlers
Make system more stable
4. Unwinding
After throwing a exception object, exception library will do
unwinding frame to find the handler which could handle the
exception object.
There are two way to do unwinding
Set jump/long jump (SJLJ) unwinding
Don’t know about the frame info
restore all registers saved in the jump-buffer by setjmp
Smaller code size but slower (store all register when enter each frame)
Configure gcc with --enable-sjlj-exceptions
Dwarf2 unwinding
Obtain eh_rame, gcc_except_table to record frame relative info
Could know which register will really corrupt and restore the register which
really needed
Code size bigger but faster
5. Dwarf2 unwinding
Startup code to support dwarf2 unwinding
_init
call frame_dummy
call __register_frame_info_base
call __do_global_ctors
call atexit (__do_global_dtors)
__register_frame_info_base
Called from crtbegin.o to register the unwind info for an object
libgcc/config.host
extra_parts="crti.o crtn.o crtbegin.o crtend.o crtbeginS.o crtendS.o“
Which will use libgcc/crtstuff.c to build startup code
6. Dwarf2 unwinding relative porting
There are three thing for Dwarf2 unwinding are
ABI specific which need porting code to handle
this part
Pass exception info to exception handler
Prologue need preserve original register value
Adjust stack pointer from unwind frame to handler
Modify return value to exception handler
After unwinding, unwinding library will modify return value to
handler and jump to handler by function return
Return value could be in
Return register
Frame stack
7. Dwarf2 unwinding relative porting
Pass exception info to exception handler
Define EH_RETURN_DATA_REGNO
The register to pass exception info
Prologue need push original value to the stack before setting
exception info
Adjust stack pointer from unwind frame to handler
Define EH_RETURN_STACKADJ_RTX
The register to contain adjust offset
Modify return value to exception handler
Define EH_RETURN_HANDLER_RTX or eh_return
pattern
To modify return value to handler
8. eh_return pattern of arm
arm_set_return_address (rtx source, rtx scratch)
{
…
/* if return address in LR_REGNUM
emit a move to change return address to handler */
if ((saved_regs & (1 << LR_REGNUM)) == 0)
emit_move_insn (gen_rtx_REG (Pmode, LR_REGNUM), source);
/* return value in stack */
else
{
}
source contain return value
9. eh_return pattern of arm
arm_set_return_address (rtx source, rtx scratch)
{
…
/* return value in stack */
else
{
if (frame_pointer_needed)
addr = plus_constant(hard_frame_pointer_rtx, -4);
else
{ /* LR will be the first saved register. */
delta = offsets->outgoing_args - (offsets->frame + 4);
If (delta >= 4096)
{
emit_insn (gen_addsi3 (scratch, stack_pointer_rtx, GEN_INT (delta & ~4095)));
addr = scratch; delta &= 4095; }
else
addr = stack_pointer_rtx;
addr = plus_constant (addr, delta);
}
emit_move_insn (gen_frame_mem (Pmode, addr), source);
}
}
source contain return value
Use fp to find return address in stack
Emit memory move to modify return address in stack
Find the return address in stack
10. Sections for dwarf2 unwinding
.eh_frame
Contains the information necessary to pop back to the
state of the machine registers and the stack at any point
higher up the call stack
.gcc_except_table
Contains information about the exception handling
"langing pads" the locations of handlers.
This is necessary so as to know when to stop
unwinding.
http://gcc.gnu.org/ml/gcc-help/2010-09/msg00116.html
11. Reference
C++ ABI for Itanium: Exception handling
http://refspecs.linuxfoundation.org/abi-eh-
1.22.htm
sjlj vs dw2 in GCC
http://stackoverflow.com/questions/318383/exce
ption-handling-models-of-gcc