4.54 Integer division-by-zero errors in C code

For targets that do not support the SDIV divide instruction, you can trap and identify integer division-by-zero errors with the appropriate C library helper functions, __aeabi_idiv0() and __rt_raise().

Trapping integer division-by-zero errors with __aeabi_idiv0()

You can trap integer division-by-zero errors with the C library helper function __aeabi_idiv0() so that division by zero returns some standard result, for example zero.
Integer division is implemented in code through the C library helper functions __aeabi_idiv() and __aeabi_uidiv(). Both functions check for division by zero.
When integer division by zero is detected, a branch to __aeabi_idiv0() is made. To trap the division by zero, therefore, you only have to place a breakpoint on __aeabi_idiv0().
The library provides two implementations of __aeabi_idiv0(). The default one does nothing, so if division by zero is detected, the division function returns zero. However, if you use signal handling, an alternative implementation is selected that calls __rt_raise(SIGFPE, DIVBYZERO).
If you provide your own version of __aeabi_idiv0(), then the division functions call this function. The function prototype for __aeabi_idiv0() is:
int __aeabi_idiv0(void);
If __aeabi_idiv0() returns a value, that value is used as the quotient returned by the division function.
On entry into __aeabi_idiv0(), the link register LR contains the address of the instruction after the call to the __aeabi_uidiv() division routine in your application code.
The offending line in the source code can be identified by looking up the line of C code in the debugger at the address given by LR.
If you want to examine parameters and save them for postmortem debugging when trapping __aeabi_idiv0, you can use the $Super$$ and $Sub$$ mechanism:
  1. Prefix __aeabi_idiv0() with $Super$$ to identify the original unpatched function __aeabi_idiv0().
  2. Use __aeabi_idiv0() prefixed with $Super$$ to call the original function directly.
  3. Prefix __aeabi_idiv0() with $Sub$$ to identify the new function to be called in place of the original version of __aeabi_idiv0().
  4. Use __aeabi_idiv0() prefixed with $Sub$$ to add processing before or after the original function __aeabi_idiv0().
The following example shows how to intercept __aeabi_div0 using the $Super$$ and $Sub$$ mechanism.
extern void $Super$$__aeabi_idiv0(void);
/* this function is called instead of the original __aeabi_idiv0() */
void $Sub$$__aeabi_idiv0()
{
    // insert code to process a divide by zero
    ...
    // call the original __aeabi_idiv0 function
    $Super$$__aeabi_idiv0();
}

Trapping integer division-by-zero errors with __rt_raise()

By default, integer division by zero returns zero. If you want to intercept division by zero, you can re-implement the C library helper function __rt_raise().
The function prototype for __rt_raise() is:
void __rt_raise(int signal, int type);
If you re-implement __rt_raise(), then the library automatically provides the signal-handling library version of __aeabi_idiv0(), which calls __rt_raise(), then that library version of __aeabi_idiv0() is included in the final image.
In that case, when a divide-by-zero error occurs, __aeabi_idiv0() calls __rt_raise(SIGFPE, DIVBYZERO). Therefore, if you re-implement __rt_raise(), you must check (signal == SIGFPE) && (type == DIVBYZERO) to determine if division by zero has occurred.
Related information
Run-time ABI for the ARM Architecture
Non-ConfidentialPDF file icon PDF versionARM DUI0375F
Copyright © 2007, 2008, 2011, 2012, 2014 ARM. All rights reserved.