Non-Confidential | PDF version | ARM DUI0375F | ||

| ||||

Home > Compiler Coding Practices > 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()`

.

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:- Prefix
`__aeabi_idiv0()`

with`$Super$$`

to identify the original unpatched function`__aeabi_idiv0()`

. - Use
`__aeabi_idiv0()`

prefixed with`$Super$$`

to call the original function directly. - Prefix
`__aeabi_idiv0()`

with`$Sub$$`

to identify the new function to be called in place of the original version of`__aeabi_idiv0()`

. - 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(); }

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.