Ignore:
Timestamp:
Mar 18, 2020, 9:07:52 AM (4 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
0f6ac828, c5fdebf
Parents:
734c9664
Message:

second pass over Andrew's Chapter 1

File:
1 edited

Legend:

Unmodified
Added
Removed
  • doc/theses/andrew_beach_MMath/unwinding.tex

    r734c9664 r2655031  
    33When a function returns, a \emph{single} stack frame is unwound, removing the
    44function's parameters and local variables, and control continues in the
    5 function caller using the caller's stack frame.  When an exception is raised,
     5function's caller using the caller's stack frame.  When an exception is raised,
    66\emph{multiple} stack frames are unwound, removing the function parameters and
    77local variables for called functions from the exception raise-frame to the
     
    1919necessary to walk the stack frames from raise to catch, checking for code that
    2020must be executed as part of terminating each frame. Walking the stack has a
    21 higher cost, and necessary information must available to detect
     21higher cost, and necessary information must be available to detect
    2222destructors/finalizers and call them.
    2323
     
    3434\section{libunwind Usage}
    3535
    36 There are two primary functions that \CFA uses in $libunwind$ to create most of
    37 the exceptional control-flow. These functions are
    38 $_Unwind_RaiseException$ and $_Unwind_ForcedUnwind$.
    39 
     36\CFA uses two primary functions in $libunwind$ to create most of its
     37exceptional control-flow: $_Unwind_RaiseException$ and $_Unwind_ForcedUnwind$.
    4038Their operation is divided into two phases: search and clean-up. The search
    4139phase -- phase 1 -- is used to scan the stack but not unwinding it. The
    42 clean-up phase -- phase 2 -- is used to during unwinding.
     40clean-up phase -- phase 2 -- is used for unwinding.
    4341
    4442% Somewhere around here I need to talk about the control structures.
     
    4947% information to helper functions.
    5048
    51 The raise-exception function uses both phases. It starts by searching for the
     49The raise-exception function uses both phases. It starts by searching for a
    5250handler, and if found, performs a clean-up phase to unwind the stack to the
    53 hander. If a handler is not found, control returns allowing the
     51handler. If a handler is not found, control returns allowing the
    5452exception-handling policy for unhandled exception to be executed.  During both
    55 phases, the raise exception function searches down the stack, calling each
     53phases, the raise-exception function searches down the stack, calling each
    5654function's \emph{personality function}.
    5755
    58 A personality function performs three tasks, although not all of them have to
    59 be present. The tasks performed are decided by the actions provided.
     56A personality function performs three tasks, although not all have to be
     57present. The tasks performed are decided by the actions provided.
    6058% Something argument something bitmask.
    6159\begin{itemize}
    6260\item$_UA_SEARCH_PHASE$ is called during the clean-up phase and means search
    63 for handlers. If the hander is found, the personality function should return
     61for handlers. If a hander is found, the personality function should return
    6462$_URC_HANDLER_FOUND$, otherwise it returns $_URC_CONTINUE_UNWIND$.
     63{\color{red}What is the connection between finding the handler and the
     64personality function?}
    6565\item$_UA_CLEANUP_PHASE$ is passed in during the clean-up phase and means part
    6666or all of the stack frame is removed. The personality function should do
     
    6969\item$_UA_HANDLER_FRAME$ means the personality function must install a
    7070handler. It is also passed in during the clean-up phase and is in addition to
    71 the clean-up action. Libunwind provides several helpers for the personality
     71the clean-up action. $libunwind$ provides several helpers for the personality
    7272function here. Once it is done, the personality function must return
    7373$_URC_INSTALL_CONTEXT$.
     
    7575
    7676Forced unwind only performs the clean-up phase. It is similar to the phase 2
    77 section of raise exception with a few changes. A simple one is that it passes
    78 in an extra action to the personality function $_UA_FORCE_UNWIND$, which means
    79 a handler cannot be installed. The most significant is the addition of the $stop$
    80 function, which is passed in as an argument to the forced unwind.
     77section of raise exception with a few changes. A simple difference is that it
     78passes in an extra action to the personality function $_UA_FORCE_UNWIND$, which
     79means a handler cannot be installed. The most difference significant is the
     80addition of the $stop$ function, which is passed in as an argument to forced
     81unwind.
    8182
    82 The stop function is a lot like a personality function. It takes an extra
    83 argument, a void pointer passed into force unwind. It may return
     83The $stop$ function is similar to a personality function. It takes an extra
     84argument: a $void$ pointer passed into force unwind. It may return
    8485$_URC_NO_REASON$ to continue unwinding or it can transfer control out of the
    8586unwind code using its own mechanism.
    8687% Is there a reason that NO_REASON is used instead of CONTINUE_UNWIND?
    87 The stop function is called once on every stack frame and once at the end of
    88 the stack. In a stack frame, it is called before the personality routine with
    89 the same arguments (except for the extra void pointer). At the end of the
    90 stack, the arguments are mostly the same, except the stack pointer stored in
    91 the context is set to null. Because of the significance of that change, both
    92 GCC and Clang add an extra action in this case $_UA_END_OF_STACK$.  The stop
    93 function may not return at the end of the stack.
     88The $stop$ function is called for each stack frame and at the end of the
     89stack. In a stack frame, it is called before the personality routine with the
     90same arguments (except for the extra $void$ pointer). At the end of the stack,
     91the arguments are mostly the same, except the stack pointer stored in the
     92context is set to null. Because of this change, both GCC and Clang add an extra
     93action in this case $_UA_END_OF_STACK$.  The $stop$ function may not return at
     94the end of the stack.
     95
     96{\color{red}This needs work as I do not understand all of it.}
     97
    9498
    9599\section{\CFA Implementation}
    96100
    97 To use $libunwind$, \CFA provides several wrappers, its own storage, the
    98 personality functions, and a stop function.
     101To use $libunwind$, \CFA provides several wrappers, its own storage,
     102personality functions, and a $stop$ function.
    99103
    100104The wrappers perform three tasks: set-up, clean-up and controlling the
    101 unwinding. The set-up allocates a copy of the \CFA exception into a handler
    102 so it can control its lifetime, and stores it in the exception context.
    103 Clean-up -- run when control exits a catch clause and return to normal code --
    104 frees the exception copy.
     105unwinding. The set-up allocates a copy of the \CFA exception into a handler to
     106control its lifetime, and stores it in the exception context.  Clean-up -- run
     107when control exits a catch clause and returns to normal code -- frees the
     108exception copy.
    105109% It however does not set up the unwind exception so we can't use any inter-
    106110% runtime/language features. Also the exception context is global.
    107111
    108 The control code in the middle is run every time a throw or re-throw is
    109 called. It uses raise exception to search for a handler and to run it if one
    110 is found. Otherwise it uses forced unwind to unwind the stack, running all
    111 destructors, before terminating the process.
     112The control code in the middle {\color{red}(In the middle of what?)} is run
     113every time a throw or re-throw is called. It uses raise exception to search for
     114a handler and to run it, if one is found. Otherwise, it uses forced unwind to
     115unwind the stack, running all destructors, before terminating the process.
    112116
    113 The stop function is very simple, it checks the end of stack flag to see if it
    114 is finished unwinding. If so, it calls exit to end the process, otherwise it
    115 tells the system to continue unwinding.
     117The $stop$ function is very simple. It checks the end of stack flag to see if
     118it is finished unwinding. If so, it calls $exit$ to end the process, otherwise
     119it tells the system {\color{red}(What system?)} to continue unwinding.
    116120% Yeah, this is going to have to change.
    117121
    118 The personality routine is much more complicated.  First, because it has to get
    119 some information about the function by scanning the LSDA (Language Specific
    120 Data Area). This allows a single personality function to be used for multiple
    121 functions and it accounts for multiple regions and possible handlers in a
    122 single function.
     122The personality routine is more complex because it has to obtain information
     123about the function by scanning the LSDA (Language Specific Data Area). This
     124step allows a single personality function to be used for multiple functions and
     125it accounts for multiple regions{\color{red}(What's a region?)} and possible
     126handlers in a single function.
    123127% Not that we do that yet.
    124128
    125 However generating the LSDA is very difficult. It requires a lot of knowledge
    126 about the location of the instruction pointer and stack layout that can be
    127 broken by optimization. So instead for frames where there are only destructors
    128 we use GCC's attribute cleanup and the -fexception flag to handle unwinding
    129 without adding our own functionality.
     129However, generating the LSDA is difficult. It requires knowledge about the
     130location of the instruction pointer and stack layout, which varies by
     131optimization levels. So for frames where there are only destructors, GCC's
     132attribute cleanup with the $-fexception$ flag is sufficient to handle unwinding.
    130133
    131 For functions that do have handlers (defined in try statements) the function
    132 is split into several functions. Everything outside the try statement is the
    133 first function, which has then has only destructors to be run during
    134 unwinding. The clauses of the try block are then converted into GCC inner
    135 functions which can be passed around with function pointers while still having
    136 access to the outer function's scope. $catchResume$ and $finally$
    137 clauses are handled separately and will not be discussed here.
     134For functions with handlers (defined in the $try$ statement) the function is
     135split into several functions. Everything outside the $try$ statement is the
     136first function, which only has destructors to be run during unwinding. The
     137catch clauses of the $try$ block are then converted into GCC inner functions,
     138which are passed via function pointers while still having access to the outer
     139function's scope. $catchResume$ and $finally$ clauses are handled separately
     140and not discussed here.
    138141
    139 The $try$ clause is converted to a function directly. The $catch$
    140 clauses are combined and then create two functions. The first is the match
    141 function which is used during the search phase to see if any of the handler
    142 here. The second it the catch function, which is a large switch-case block
    143 with the different handlers. All of these function do not interact with
    144 unwinding except for running destructors and so can be handled by GCC.
     142The $try$ clause {\color{red}You have $try$ statement, $try$ block, and $try$
     143clause, which need clarification.)} is converted to a function directly. The
     144$catch$ clauses are combined into two functions. The first is the match
     145function, which is used during the search phase to find a handler. The second
     146it the catch function, which is a large switch-case for the different
     147handlers. These functions do not interact with unwinding except for running
     148destructors and so can be handled by GCC.
    145149
    146 These three functions are passed into $try_terminate$, an internal
    147 function that represents the try statement. This is the only function with
    148 our personality function as well as assembly statements that create the LSDA.
    149 In normal execution all the function does is call the try block closure and
    150 return once that has finished executing. However using $libunwind$ its
    151 personality function now handles exception matching and catching.
     150These three functions are passed into $try_terminate$, an internal function
     151that represents the $try$ statement. This function uses the generated
     152personality functions as well as assembly statements to create the LSDA.  In
     153normal execution, this function only calls the $try$ block closure. However,
     154using $libunwind$, its personality function now handles exception matching and
     155catching. {\color{red}(I don't understand the last sentence.)}
    152156
    153 During the search phase the personality function retrieves the match function
     157During the search phase, the personality function retrieves the match function
    154158from the stack using the saved stack pointer. The function is called, either
    155 returning 0 for no match or the index (a positive integer) of the handler
    156 that will handle it. The if a handler was found the personality function
    157 reports it after saving the index to the exception context.
     159returning 0 for no match or the index (a positive integer) of the handler for a
     160match. If a handler is found, the personality function reports it after saving
     161the index to the exception context.
    158162
    159163During the clean-up phase there is nothing for the personality function to
    160 clean-up in $try_terminate$. So if this is not the handler frame
    161 unwinding continues. If this is the handler frame than control is transferred
    162 to the catch function, giving it the exception and the handler index.
     164clean-up in $try_terminate$. So if this is not the handler frame, unwinding
     165continues. If this is the handler frame, control is transferred to the catch
     166function, giving it the exception and the handler index.
     167
     168{\color{red}This needs work as I do not understand all of it.}
Note: See TracChangeset for help on using the changeset viewer.