neingeist
/
arduinisten
Archived
1
0
Fork 0
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

197 lines
8.5 KiB
HTML

<html lang="en">
<head>
<title>ARM Unwinding Tutorial - Using as</title>
<meta http-equiv="Content-Type" content="text/html">
<meta name="description" content="Using as">
<meta name="generator" content="makeinfo 4.7">
<link title="Top" rel="start" href="index.html#Top">
<link rel="up" href="ARM_002dDependent.html#ARM_002dDependent" title="ARM-Dependent">
<link rel="prev" href="ARM-Mapping-Symbols.html#ARM-Mapping-Symbols" title="ARM Mapping Symbols">
<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
<!--
This file documents the GNU Assembler "as".
Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001, 2002,
2006, 2007 Free Software Foundation, Inc.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1
or any later version published by the Free Software Foundation;
with no Invariant Sections, with no Front-Cover Texts, and with no
Back-Cover Texts. A copy of the license is included in the
section entitled ``GNU Free Documentation License''.
man end-->
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
pre.display { font-family:inherit }
pre.format { font-family:inherit }
pre.smalldisplay { font-family:inherit; font-size:smaller }
pre.smallformat { font-family:inherit; font-size:smaller }
pre.smallexample { font-size:smaller }
pre.smalllisp { font-size:smaller }
span.sc { font-variant:small-caps }
span.roman { font-family: serif; font-weight: normal; }
--></style>
</head>
<body>
<div class="node">
<p>
<a name="ARM-Unwinding-Tutorial"></a>Previous:&nbsp;<a rel="previous" accesskey="p" href="ARM-Mapping-Symbols.html#ARM-Mapping-Symbols">ARM Mapping Symbols</a>,
Up:&nbsp;<a rel="up" accesskey="u" href="ARM_002dDependent.html#ARM_002dDependent">ARM-Dependent</a>
<hr><br>
</div>
<h4 class="subsection">9.3.7 Unwinding</h4>
<p>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.
<p>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.
<p>To illustrate the use of these pseudo ops, we will examine the code
that G++ generates for the following C++ input:
<pre class="verbatim">
void callee (int *);
int
caller ()
{
int i;
callee (&amp;i);
return i;
}
</pre>
<p>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.
<p>The code generated by one particular version of G++ when compiling the
example above is:
<pre class="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
</pre>
<p>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.
<p>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</code> instruction above. At each call site, the same saved
registers (including <code>lr</code>, which indicates the return address)
must be located in the same locations relative to the frame pointer.
<p>The <code>.fnstart</code> (see <a href="arm_005ffnstart.html#arm_005ffnstart">.fnstart pseudo op</a>) pseudo
op appears immediately before the first instruction of the function
while the <code>.fnend</code> (see <a href="arm_005ffnend.html#arm_005ffnend">.fnend pseudo op</a>) pseudo
op appears immediately after the last instruction of the function.
These pseudo ops specify the range of the function.
<p>Only the order of the other pseudos ops (e.g., <code>.setfp</code> or
<code>.pad</code>) 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</code> in the same order, but
immediately after <code>.fnstart</code>.
<p>The <code>.save</code> (see <a href="arm_005fsave.html#arm_005fsave">.save pseudo op</a>) 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</code> pseudo op is a list of registers to save. If a register
is &ldquo;callee-saved&rdquo; (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</code>
pseudo op restores these registers in the function epilogue, as is
done with the <code>ldmfd</code> instruction above.)
<p>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</code> 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</code> pseudo
op to indicate that you have done so.
<p>The <code>.pad</code> (see <a href="arm_005fpad.html#arm_005fpad">.pad</a>) 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.)
<p>The <code>.setfp</code> (see <a href="arm_005fsetfp.html#arm_005fsetfp">.setfp pseudo op</a>) pseudo op
indicates the register that contains the frame pointer. The first
argument is the register that is set, which is typically <code>fp</code>.
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.
<p>If you do not use a frame pointer, then you should not use the
<code>.setfp</code> 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.
<p>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</cite> available from <a href="http://infocenter.arm.com">http://infocenter.arm.com</a>.
<!-- Copyright 2006 -->
<!-- Free Software Foundation, Inc. -->
<!-- This is part of the GAS manual. -->
<!-- For copying conditions, see the file as.texinfo. -->
</body></html>