|
|
|
@ -23,6 +23,7 @@ |
|
|
|
* ARM Directives:: ARM Machine Directives |
|
|
|
* ARM Opcodes:: Opcodes |
|
|
|
* ARM Mapping Symbols:: Mapping Symbols |
|
|
|
* ARM Unwinding Tutorial:: Unwinding |
|
|
|
@end menu |
|
|
|
|
|
|
|
@node ARM Options |
|
|
|
@ -502,10 +503,12 @@ it prevents accurate control of the placement of literal pools. |
|
|
|
@item .pool |
|
|
|
This is a synonym for .ltorg. |
|
|
|
|
|
|
|
@anchor{arm_fnstart} |
|
|
|
@cindex @code{.fnstart} directive, ARM |
|
|
|
@item .fnstart |
|
|
|
Marks the start of a function with an unwind table entry. |
|
|
|
|
|
|
|
@anchor{arm_fnend} |
|
|
|
@cindex @code{.fnend} directive, ARM |
|
|
|
@item .fnend |
|
|
|
Marks the end of a function with an unwind table entry. The unwind index |
|
|
|
@ -538,6 +541,7 @@ entry for that function. Anything between this directive and the |
|
|
|
Must be preceded by a @code{.personality} or @code{.personalityindex} |
|
|
|
directive. |
|
|
|
|
|
|
|
@anchor{arm_save} |
|
|
|
@cindex @code{.save} directive, ARM |
|
|
|
@item .save @var{reglist} |
|
|
|
Generate unwinder annotations to restore the registers in @var{reglist}. |
|
|
|
@ -585,18 +589,21 @@ instruction. |
|
|
|
Since FLDMX and FSTMX are now deprecated, this directive should be |
|
|
|
used in favour of @code{.save} for saving VFP registers for ARMv6 and above. |
|
|
|
|
|
|
|
@anchor{arm_pad} |
|
|
|
@cindex @code{.pad} directive, ARM |
|
|
|
@item .pad #@var{count} |
|
|
|
Generate unwinder annotations for a stack adjustment of @var{count} bytes. |
|
|
|
A positive value indicates the function prologue allocated stack space by |
|
|
|
decrementing the stack pointer. |
|
|
|
|
|
|
|
@anchor{arm_movsp} |
|
|
|
@cindex @code{.movsp} directive, ARM |
|
|
|
@item .movsp @var{reg} [, #@var{offset}] |
|
|
|
Tell the unwinder that @var{reg} contains an offset from the current |
|
|
|
stack pointer. If @var{offset} is not specified then it is assumed to be |
|
|
|
zero. |
|
|
|
|
|
|
|
@anchor{arm_setfp} |
|
|
|
@cindex @code{.setfp} directive, ARM |
|
|
|
@item .setfp @var{fpreg}, @var{spreg} [, #@var{offset}] |
|
|
|
Make all unwinder annotations relaive to a frame pointer. Without this |
|
|
|
@ -747,3 +754,149 @@ specification is not implemented. This is because they have been |
|
|
|
dropped from the new EABI and so tools cannot rely upon their |
|
|
|
presence. |
|
|
|
|
|
|
|
@node ARM Unwinding Tutorial |
|
|
|
@section Unwinding |
|
|
|
|
|
|
|
The ABI for the ARM Architecture specifies a standard format for |
|
|
|
exception unwind information. This information is used when an |
|
|
|
exception is thrown to determine where control should be transferred. |
|
|
|
In particular, the unwind information is used to determine which |
|
|
|
function called the function that threw the exception, and which |
|
|
|
function called that one, and so forth. This information is also used |
|
|
|
to restore the values of callee-saved registers in the function |
|
|
|
catching the exception. |
|
|
|
|
|
|
|
If you are writing functions in assembly code, and those functions |
|
|
|
call other functions that throw exceptions, you must use assembly |
|
|
|
pseudo ops to ensure that appropriate exception unwind information is |
|
|
|
generated. Otherwise, if one of the functions called by your assembly |
|
|
|
code throws an exception, the run-time library will be unable to |
|
|
|
unwind the stack through your assembly code and your program will not |
|
|
|
behave correctly. |
|
|
|
|
|
|
|
To illustrate the use of these pseudo ops, we will examine the code |
|
|
|
that G++ generates for the following C++ input: |
|
|
|
|
|
|
|
@verbatim |
|
|
|
void callee (int *); |
|
|
|
|
|
|
|
int |
|
|
|
caller () |
|
|
|
{ |
|
|
|
int i; |
|
|
|
callee (&i); |
|
|
|
return i; |
|
|
|
} |
|
|
|
@end verbatim |
|
|
|
|
|
|
|
This example does not show how to throw or catch an exception from |
|
|
|
assembly code. That is a much more complex operation and should |
|
|
|
always be done in a high-level language, such as C++, that directly |
|
|
|
supports exceptions. |
|
|
|
|
|
|
|
The code generated by one particular version of G++ when compiling the |
|
|
|
example above is: |
|
|
|
|
|
|
|
@verbatim |
|
|
|
_Z6callerv: |
|
|
|
.fnstart |
|
|
|
.LFB2: |
|
|
|
@ Function supports interworking. |
|
|
|
@ args = 0, pretend = 0, frame = 8 |
|
|
|
@ frame_needed = 1, uses_anonymous_args = 0 |
|
|
|
stmfd sp!, {fp, lr} |
|
|
|
.save {fp, lr} |
|
|
|
.LCFI0: |
|
|
|
.setfp fp, sp, #4 |
|
|
|
add fp, sp, #4 |
|
|
|
.LCFI1: |
|
|
|
.pad #8 |
|
|
|
sub sp, sp, #8 |
|
|
|
.LCFI2: |
|
|
|
sub r3, fp, #8 |
|
|
|
mov r0, r3 |
|
|
|
bl _Z6calleePi |
|
|
|
ldr r3, [fp, #-8] |
|
|
|
mov r0, r3 |
|
|
|
sub sp, fp, #4 |
|
|
|
ldmfd sp!, {fp, lr} |
|
|
|
bx lr |
|
|
|
.LFE2: |
|
|
|
.fnend |
|
|
|
@end verbatim |
|
|
|
|
|
|
|
Of course, the sequence of instructions varies based on the options |
|
|
|
you pass to GCC and on the version of GCC in use. The exact |
|
|
|
instructions are not important since we are focusing on the pseudo ops |
|
|
|
that are used to generate unwind information. |
|
|
|
|
|
|
|
An important assumption made by the unwinder is that the stack frame |
|
|
|
does not change during the body of the function. In particular, since |
|
|
|
we assume that the assembly code does not itself throw an exception, |
|
|
|
the only point where an exception can be thrown is from a call, such |
|
|
|
as the @code{bl} instruction above. At each call site, the same saved |
|
|
|
registers (including @code{lr}, which indicates the return address) |
|
|
|
must be located in the same locations relative to the frame pointer. |
|
|
|
|
|
|
|
The @code{.fnstart} (@pxref{arm_fnstart,,.fnstart pseudo op}) pseudo |
|
|
|
op appears immediately before the first instruction of the function |
|
|
|
while the @code{.fnend} (@pxref{arm_fnend,,.fnend pseudo op}) pseudo |
|
|
|
op appears immediately after the last instruction of the function. |
|
|
|
These pseudo ops specify the range of the function. |
|
|
|
|
|
|
|
Only the order of the other pseudos ops (e.g., @code{.setfp} or |
|
|
|
@code{.pad}) matters; their exact locations are irrelevant. In the |
|
|
|
example above, the compiler emits the pseudo ops with particular |
|
|
|
instructions. That makes it easier to understand the code, but it is |
|
|
|
not required for correctness. It would work just as well to emit all |
|
|
|
of the pseudo ops other than @code{.fnend} in the same order, but |
|
|
|
immediately after @code{.fnstart}. |
|
|
|
|
|
|
|
The @code{.save} (@pxref{arm_save,,.save pseudo op}) pseudo op |
|
|
|
indicates registers that have been saved to the stack so that they can |
|
|
|
be restored before the function returns. The argument to the |
|
|
|
@code{.save} pseudo op is a list of registers to save. If a register |
|
|
|
is ``callee-saved'' (as specified by the ABI) and is modified by the |
|
|
|
function you are writing, then your code must save the value before it |
|
|
|
is modified and restore the original value before the function |
|
|
|
returns. If an exception is thrown, the run-time library restores the |
|
|
|
values of these registers from their locations on the stack before |
|
|
|
returning control to the exception handler. (Of course, if an |
|
|
|
exception is not thrown, the function that contains the @code{.save} |
|
|
|
pseudo op restores these registers in the function epilogue, as is |
|
|
|
done with the @code{ldmfd} instruction above.) |
|
|
|
|
|
|
|
You do not have to save callee-saved registers at the very beginning |
|
|
|
of the function and you do not need to use the @code{.save} pseudo op |
|
|
|
immediately following the point at which the registers are saved. |
|
|
|
However, if you modify a callee-saved register, you must save it on |
|
|
|
the stack before modifying it and before calling any functions which |
|
|
|
might throw an exception. And, you must use the @code{.save} pseudo |
|
|
|
op to indicate that you have done so. |
|
|
|
|
|
|
|
The @code{.pad} (@pxref{arm_pad,,.pad}) pseudo op indicates a |
|
|
|
modification of the stack pointer that does not save any registers. |
|
|
|
The argument is the number of bytes (in decimal) that are subtracted |
|
|
|
from the stack pointer. (On ARM CPUs, the stack grows downwards, so |
|
|
|
subtracting from the stack pointer increases the size of the stack.) |
|
|
|
|
|
|
|
The @code{.setfp} (@pxref{arm_setfp,,.setfp pseudo op}) pseudo op |
|
|
|
indicates the register that contains the frame pointer. The first |
|
|
|
argument is the register that is set, which is typically @code{fp}. |
|
|
|
The second argument indicates the register from which the frame |
|
|
|
pointer takes its value. The third argument, if present, is the value |
|
|
|
(in decimal) added to the register specified by the second argument to |
|
|
|
compute the value of the frame pointer. You should not modify the |
|
|
|
frame pointer in the body of the function. |
|
|
|
|
|
|
|
If you do not use a frame pointer, then you should not use the |
|
|
|
@code{.setfp} pseudo op. If you do not use a frame pointer, then you |
|
|
|
should avoid modifying the stack pointer outside of the function |
|
|
|
prologue. Otherwise, the run-time library will be unable to find |
|
|
|
saved registers when it is unwinding the stack. |
|
|
|
|
|
|
|
The pseudo ops described above are sufficient for writing assembly |
|
|
|
code that calls functions which may throw exceptions. If you need to |
|
|
|
know more about the object-file format used to represent unwind |
|
|
|
information, you may consult the @cite{Exception Handling ABI for the |
|
|
|
ARM Architecture} available from @uref{http://infocenter.arm.com}. |
|
|
|
|