Changeset 2655031
- Timestamp:
- Mar 18, 2020, 9:07:52 AM (5 years ago)
- 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
- Location:
- doc/theses/andrew_beach_MMath
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/andrew_beach_MMath/thesis.tex
r734c9664 r2655031 4 4 \usepackage{fullpage} 5 5 \setlength{\textheight}{8.75in} 6 \renewcommand\labelitemi{\footnotesize$\bullet$} % shrink bullet for level 1 itemize 7 \usepackage{lmodern} % bold typewriter font 6 8 7 9 \usepackage{listings} % format program code -
doc/theses/andrew_beach_MMath/unwinding.tex
r734c9664 r2655031 3 3 When a function returns, a \emph{single} stack frame is unwound, removing the 4 4 function's parameters and local variables, and control continues in the 5 function caller using the caller's stack frame. When an exception is raised,5 function's caller using the caller's stack frame. When an exception is raised, 6 6 \emph{multiple} stack frames are unwound, removing the function parameters and 7 7 local variables for called functions from the exception raise-frame to the … … 19 19 necessary to walk the stack frames from raise to catch, checking for code that 20 20 must be executed as part of terminating each frame. Walking the stack has a 21 higher cost, and necessary information must available to detect21 higher cost, and necessary information must be available to detect 22 22 destructors/finalizers and call them. 23 23 … … 34 34 \section{libunwind Usage} 35 35 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 37 exceptional control-flow: $_Unwind_RaiseException$ and $_Unwind_ForcedUnwind$. 40 38 Their operation is divided into two phases: search and clean-up. The search 41 39 phase -- phase 1 -- is used to scan the stack but not unwinding it. The 42 clean-up phase -- phase 2 -- is used to duringunwinding.40 clean-up phase -- phase 2 -- is used for unwinding. 43 41 44 42 % Somewhere around here I need to talk about the control structures. … … 49 47 % information to helper functions. 50 48 51 The raise-exception function uses both phases. It starts by searching for the49 The raise-exception function uses both phases. It starts by searching for a 52 50 handler, and if found, performs a clean-up phase to unwind the stack to the 53 hand er. If a handler is not found, control returns allowing the51 handler. If a handler is not found, control returns allowing the 54 52 exception-handling policy for unhandled exception to be executed. During both 55 phases, the raise 53 phases, the raise-exception function searches down the stack, calling each 56 54 function's \emph{personality function}. 57 55 58 A personality function performs three tasks, although not all of them have to59 bepresent. The tasks performed are decided by the actions provided.56 A personality function performs three tasks, although not all have to be 57 present. The tasks performed are decided by the actions provided. 60 58 % Something argument something bitmask. 61 59 \begin{itemize} 62 60 \item$_UA_SEARCH_PHASE$ is called during the clean-up phase and means search 63 for handlers. If thehander is found, the personality function should return61 for handlers. If a hander is found, the personality function should return 64 62 $_URC_HANDLER_FOUND$, otherwise it returns $_URC_CONTINUE_UNWIND$. 63 {\color{red}What is the connection between finding the handler and the 64 personality function?} 65 65 \item$_UA_CLEANUP_PHASE$ is passed in during the clean-up phase and means part 66 66 or all of the stack frame is removed. The personality function should do … … 69 69 \item$_UA_HANDLER_FRAME$ means the personality function must install a 70 70 handler. It is also passed in during the clean-up phase and is in addition to 71 the clean-up action. Libunwindprovides several helpers for the personality71 the clean-up action. $libunwind$ provides several helpers for the personality 72 72 function here. Once it is done, the personality function must return 73 73 $_URC_INSTALL_CONTEXT$. … … 75 75 76 76 Forced 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. 77 section of raise exception with a few changes. A simple difference is that it 78 passes in an extra action to the personality function $_UA_FORCE_UNWIND$, which 79 means a handler cannot be installed. The most difference significant is the 80 addition of the $stop$ function, which is passed in as an argument to forced 81 unwind. 81 82 82 The stop function is a lot likea personality function. It takes an extra83 argument , a voidpointer passed into force unwind. It may return83 The $stop$ function is similar to a personality function. It takes an extra 84 argument: a $void$ pointer passed into force unwind. It may return 84 85 $_URC_NO_REASON$ to continue unwinding or it can transfer control out of the 85 86 unwind code using its own mechanism. 86 87 % 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. 88 The $stop$ function is called for each stack frame and at the end of the 89 stack. In a stack frame, it is called before the personality routine with the 90 same arguments (except for the extra $void$ pointer). At the end of the stack, 91 the arguments are mostly the same, except the stack pointer stored in the 92 context is set to null. Because of this change, both GCC and Clang add an extra 93 action in this case $_UA_END_OF_STACK$. The $stop$ function may not return at 94 the end of the stack. 95 96 {\color{red}This needs work as I do not understand all of it.} 97 94 98 95 99 \section{\CFA Implementation} 96 100 97 To use $libunwind$, \CFA provides several wrappers, its own storage, the98 personality functions, and a stopfunction.101 To use $libunwind$, \CFA provides several wrappers, its own storage, 102 personality functions, and a $stop$ function. 99 103 100 104 The 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 theexception copy.105 unwinding. The set-up allocates a copy of the \CFA exception into a handler to 106 control its lifetime, and stores it in the exception context. Clean-up -- run 107 when control exits a catch clause and returns to normal code -- frees the 108 exception copy. 105 109 % It however does not set up the unwind exception so we can't use any inter- 106 110 % runtime/language features. Also the exception context is global. 107 111 108 The control code in the middle is run every time a throw or re-throw is109 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.112 The control code in the middle {\color{red}(In the middle of what?)} is run 113 every time a throw or re-throw is called. It uses raise exception to search for 114 a handler and to run it, if one is found. Otherwise, it uses forced unwind to 115 unwind the stack, running all destructors, before terminating the process. 112 116 113 The stop function is very simple, it checks the end of stack flag to see if it114 i s finished unwinding. If so, it calls exit to end the process, otherwise it115 tells the systemto continue unwinding.117 The $stop$ function is very simple. It checks the end of stack flag to see if 118 it is finished unwinding. If so, it calls $exit$ to end the process, otherwise 119 it tells the system {\color{red}(What system?)} to continue unwinding. 116 120 % Yeah, this is going to have to change. 117 121 118 The personality routine is m uch more complicated. First, because it has to get119 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.122 The personality routine is more complex because it has to obtain information 123 about the function by scanning the LSDA (Language Specific Data Area). This 124 step allows a single personality function to be used for multiple functions and 125 it accounts for multiple regions{\color{red}(What's a region?)} and possible 126 handlers in a single function. 123 127 % Not that we do that yet. 124 128 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. 129 However, generating the LSDA is difficult. It requires knowledge about the 130 location of the instruction pointer and stack layout, which varies by 131 optimization levels. So for frames where there are only destructors, GCC's 132 attribute cleanup with the $-fexception$ flag is sufficient to handle unwinding. 130 133 131 For functions that do have handlers (defined in try statements) the function132 is split into several functions. Everything outside the trystatement is the133 first function, which has then has only destructors to be run during134 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 bediscussed here.134 For functions with handlers (defined in the $try$ statement) the function is 135 split into several functions. Everything outside the $try$ statement is the 136 first function, which only has destructors to be run during unwinding. The 137 catch clauses of the $try$ block are then converted into GCC inner functions, 138 which are passed via function pointers while still having access to the outer 139 function's scope. $catchResume$ and $finally$ clauses are handled separately 140 and not discussed here. 138 141 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. 142 The $try$ clause {\color{red}You have $try$ statement, $try$ block, and $try$ 143 clause, which need clarification.)} is converted to a function directly. The 144 $catch$ clauses are combined into two functions. The first is the match 145 function, which is used during the search phase to find a handler. The second 146 it the catch function, which is a large switch-case for the different 147 handlers. These functions do not interact with unwinding except for running 148 destructors and so can be handled by GCC. 145 149 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. 150 These three functions are passed into $try_terminate$, an internal function 151 that represents the $try$ statement. This function uses the generated 152 personality functions as well as assembly statements to create the LSDA. In 153 normal execution, this function only calls the $try$ block closure. However, 154 using $libunwind$, its personality function now handles exception matching and 155 catching. {\color{red}(I don't understand the last sentence.)} 152 156 153 During the search phase the personality function retrieves the match function157 During the search phase, the personality function retrieves the match function 154 158 from 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 savingthe index to the exception context.159 returning 0 for no match or the index (a positive integer) of the handler for a 160 match. If a handler is found, the personality function reports it after saving 161 the index to the exception context. 158 162 159 163 During 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. 164 clean-up in $try_terminate$. So if this is not the handler frame, unwinding 165 continues. If this is the handler frame, control is transferred to the catch 166 function, 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.