 RealView Compiler User's Guide |
|
| Integer divisionInteger division‑by‑zero errors can be trapped and identified by re‑implementing the appropriate C library helper functions. Trapping division-by-zero errors in codeThere are two ways you can trap integer division-by-zero errors. Either: Re-implement 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 need only to place a breakpoint on __aeabi_idiv0. See the Run-time ABI for the ARM Architecture for more information on the AEABI functions __aeabi_idiv, __aeabi_uidiv, and __aeabi_idiv0. This can be found at http://www.arm.com/products/DevTools/ABI.html. Re-implement the C library helper function __rt_raise to deal with the signal. By default, integer division by zero raises a signal. To intercept divide by zero, therefore, you can re-implement __rt_raise. This function has prototype:
void __rt_raise(int signal, int type)
When a divide-by-zero error occurs, __aeabi_idiv0 calls __rt_raise(2, 2). Therefore, in your implementation of __rt_raise, you must check (signal == 2) && (type == 2) to determine if division by zero has occurred. For more information, see:
Identifying division-by-zero errors in codeOn 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. To identify the offending line in your source code, you can simply look up the line of C code in the debugger at the address given by LR. To save parameters for post-mortem debugging you must intercept __aeabi_idiv0. Use the $Super$$ and $Sub$$ mechanism to intervene in all calls to __aeabi_idiv0: $Super$$Prefix __aeabi_idiv0 with $Super$$ to identify the original unpatched function __aeabi_idiv0. Use this to call the original function directly. $Sub$$Prefix __aeabi_idiv0 with $Sub$$ to identify the new function to be called in place of the original version of __aeabi_idiv0. Use this to add processing before or after the original function __aeabi_idiv0.
Example 4.4 illustrates the use of the $Super$$ and $Sub$$ mechanism to intercept __aeabi_div0. See Using $Super$$ and $Sub$$ to override symbol definitions in the Linker Guide for more information on using $Super$$ and $Sub$$. Example 4.4. Intercepting __aeabi_div0 using $Super$$ and $Sub$$
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();
}
|
|