GDB (API)
|
00001 /* Cleanup routines for GDB, the GNU debugger. 00002 00003 Copyright (C) 1986-2013 Free Software Foundation, Inc. 00004 00005 This file is part of GDB. 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00019 00020 #include "defs.h" 00021 #include "gdb_assert.h" 00022 00023 /* The cleanup list records things that have to be undone 00024 if an error happens (descriptors to be closed, memory to be freed, etc.) 00025 Each link in the chain records a function to call and an 00026 argument to give it. 00027 00028 Use make_cleanup to add an element to the cleanup chain. 00029 Use do_cleanups to do all cleanup actions back to a given 00030 point in the chain. Use discard_cleanups to remove cleanups 00031 from the chain back to a given point, not doing them. 00032 00033 If the argument is pointer to allocated memory, then you need 00034 to additionally set the 'free_arg' member to a function that will 00035 free that memory. This function will be called both when the cleanup 00036 is executed and when it's discarded. */ 00037 00038 struct cleanup 00039 { 00040 struct cleanup *next; 00041 void (*function) (void *); 00042 void (*free_arg) (void *); 00043 void *arg; 00044 }; 00045 00046 /* Used to mark the end of a cleanup chain. 00047 The value is chosen so that it: 00048 - is non-NULL so that make_cleanup never returns NULL, 00049 - causes a segv if dereferenced 00050 [though this won't catch errors that a value of, say, 00051 ((struct cleanup *) -1) will] 00052 - displays as something useful when printed in gdb. 00053 This is const for a bit of extra robustness. 00054 It is initialized to coax gcc into putting it into .rodata. 00055 All fields are initialized to survive -Wextra. */ 00056 static const struct cleanup sentinel_cleanup = { 0, 0, 0, 0 }; 00057 00058 /* Handy macro to use when referring to sentinel_cleanup. */ 00059 #define SENTINEL_CLEANUP ((struct cleanup *) &sentinel_cleanup) 00060 00061 /* Chain of cleanup actions established with make_cleanup, 00062 to be executed if an error happens. */ 00063 static struct cleanup *cleanup_chain = SENTINEL_CLEANUP; 00064 00065 /* Chain of cleanup actions established with make_final_cleanup, 00066 to be executed when gdb exits. */ 00067 static struct cleanup *final_cleanup_chain = SENTINEL_CLEANUP; 00068 00069 /* Main worker routine to create a cleanup. 00070 PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain. 00071 FUNCTION is the function to call to perform the cleanup. 00072 ARG is passed to FUNCTION when called. 00073 FREE_ARG, if non-NULL, is called after the cleanup is performed. 00074 00075 The result is a pointer to the previous chain pointer 00076 to be passed later to do_cleanups or discard_cleanups. */ 00077 00078 static struct cleanup * 00079 make_my_cleanup2 (struct cleanup **pmy_chain, make_cleanup_ftype *function, 00080 void *arg, void (*free_arg) (void *)) 00081 { 00082 struct cleanup *new 00083 = (struct cleanup *) xmalloc (sizeof (struct cleanup)); 00084 struct cleanup *old_chain = *pmy_chain; 00085 00086 new->next = *pmy_chain; 00087 new->function = function; 00088 new->free_arg = free_arg; 00089 new->arg = arg; 00090 *pmy_chain = new; 00091 00092 gdb_assert (old_chain != NULL); 00093 return old_chain; 00094 } 00095 00096 /* Worker routine to create a cleanup without a destructor. 00097 PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain. 00098 FUNCTION is the function to call to perform the cleanup. 00099 ARG is passed to FUNCTION when called. 00100 00101 The result is a pointer to the previous chain pointer 00102 to be passed later to do_cleanups or discard_cleanups. */ 00103 00104 static struct cleanup * 00105 make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function, 00106 void *arg) 00107 { 00108 return make_my_cleanup2 (pmy_chain, function, arg, NULL); 00109 } 00110 00111 /* Add a new cleanup to the cleanup_chain, 00112 and return the previous chain pointer 00113 to be passed later to do_cleanups or discard_cleanups. 00114 Args are FUNCTION to clean up with, and ARG to pass to it. */ 00115 00116 struct cleanup * 00117 make_cleanup (make_cleanup_ftype *function, void *arg) 00118 { 00119 return make_my_cleanup (&cleanup_chain, function, arg); 00120 } 00121 00122 /* Same as make_cleanup except also includes TDOR, a destructor to free ARG. 00123 DTOR is invoked when the cleanup is performed or when it is discarded. */ 00124 00125 struct cleanup * 00126 make_cleanup_dtor (make_cleanup_ftype *function, void *arg, 00127 void (*dtor) (void *)) 00128 { 00129 return make_my_cleanup2 (&cleanup_chain, 00130 function, arg, dtor); 00131 } 00132 00133 /* Same as make_cleanup except the cleanup is added to final_cleanup_chain. */ 00134 00135 struct cleanup * 00136 make_final_cleanup (make_cleanup_ftype *function, void *arg) 00137 { 00138 return make_my_cleanup (&final_cleanup_chain, function, arg); 00139 } 00140 00141 /* Worker routine to perform cleanups. 00142 PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain. 00143 OLD_CHAIN is the result of a "make" cleanup routine. 00144 Cleanups are performed until we get back to the old end of the chain. */ 00145 00146 static void 00147 do_my_cleanups (struct cleanup **pmy_chain, 00148 struct cleanup *old_chain) 00149 { 00150 struct cleanup *ptr; 00151 00152 while ((ptr = *pmy_chain) != old_chain) 00153 { 00154 *pmy_chain = ptr->next; /* Do this first in case of recursion. */ 00155 (*ptr->function) (ptr->arg); 00156 if (ptr->free_arg) 00157 (*ptr->free_arg) (ptr->arg); 00158 xfree (ptr); 00159 } 00160 } 00161 00162 /* Return a value that can be passed to do_cleanups, do_final_cleanups to 00163 indicate perform all cleanups. */ 00164 00165 struct cleanup * 00166 all_cleanups (void) 00167 { 00168 return SENTINEL_CLEANUP; 00169 } 00170 00171 /* Discard cleanups and do the actions they describe 00172 until we get back to the point OLD_CHAIN in the cleanup_chain. */ 00173 00174 void 00175 do_cleanups (struct cleanup *old_chain) 00176 { 00177 do_my_cleanups (&cleanup_chain, old_chain); 00178 } 00179 00180 /* Discard cleanups and do the actions they describe 00181 until we get back to the point OLD_CHAIN in the final_cleanup_chain. */ 00182 00183 void 00184 do_final_cleanups (struct cleanup *old_chain) 00185 { 00186 do_my_cleanups (&final_cleanup_chain, old_chain); 00187 } 00188 00189 /* Main worker routine to discard cleanups. 00190 PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain. 00191 OLD_CHAIN is the result of a "make" cleanup routine. 00192 Cleanups are discarded until we get back to the old end of the chain. */ 00193 00194 static void 00195 discard_my_cleanups (struct cleanup **pmy_chain, 00196 struct cleanup *old_chain) 00197 { 00198 struct cleanup *ptr; 00199 00200 while ((ptr = *pmy_chain) != old_chain) 00201 { 00202 *pmy_chain = ptr->next; 00203 if (ptr->free_arg) 00204 (*ptr->free_arg) (ptr->arg); 00205 xfree (ptr); 00206 } 00207 } 00208 00209 /* Discard cleanups, not doing the actions they describe, 00210 until we get back to the point OLD_CHAIN in the cleanup chain. */ 00211 00212 void 00213 discard_cleanups (struct cleanup *old_chain) 00214 { 00215 discard_my_cleanups (&cleanup_chain, old_chain); 00216 } 00217 00218 /* Discard final cleanups, not doing the actions they describe, 00219 until we get back to the point OLD_CHAIN in the final cleanup chain. */ 00220 00221 void 00222 discard_final_cleanups (struct cleanup *old_chain) 00223 { 00224 discard_my_cleanups (&final_cleanup_chain, old_chain); 00225 } 00226 00227 /* Main worker routine to save cleanups. 00228 PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain. 00229 The chain is emptied and the result is a pointer to the old chain. */ 00230 00231 static struct cleanup * 00232 save_my_cleanups (struct cleanup **pmy_chain) 00233 { 00234 struct cleanup *old_chain = *pmy_chain; 00235 00236 *pmy_chain = SENTINEL_CLEANUP; 00237 return old_chain; 00238 } 00239 00240 /* Set the cleanup_chain to 0, and return the old cleanup_chain. */ 00241 00242 struct cleanup * 00243 save_cleanups (void) 00244 { 00245 return save_my_cleanups (&cleanup_chain); 00246 } 00247 00248 /* Set the final_cleanup_chain to 0, and return the old 00249 final_cleanup_chain. */ 00250 00251 struct cleanup * 00252 save_final_cleanups (void) 00253 { 00254 return save_my_cleanups (&final_cleanup_chain); 00255 } 00256 00257 /* Main worker routine to save cleanups. 00258 PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain. 00259 The chain is restored from CHAIN. */ 00260 00261 static void 00262 restore_my_cleanups (struct cleanup **pmy_chain, struct cleanup *chain) 00263 { 00264 if (*pmy_chain != SENTINEL_CLEANUP) 00265 internal_warning (__FILE__, __LINE__, 00266 _("restore_my_cleanups has found a stale cleanup")); 00267 00268 *pmy_chain = chain; 00269 } 00270 00271 /* Restore the cleanup chain from a previously saved chain. */ 00272 00273 void 00274 restore_cleanups (struct cleanup *chain) 00275 { 00276 restore_my_cleanups (&cleanup_chain, chain); 00277 } 00278 00279 /* Restore the final cleanup chain from a previously saved chain. */ 00280 00281 void 00282 restore_final_cleanups (struct cleanup *chain) 00283 { 00284 restore_my_cleanups (&final_cleanup_chain, chain); 00285 } 00286 00287 /* Provide a known function that does nothing, to use as a base for 00288 a possibly long chain of cleanups. This is useful where we 00289 use the cleanup chain for handling normal cleanups as well as dealing 00290 with cleanups that need to be done as a result of a call to error(). 00291 In such cases, we may not be certain where the first cleanup is, unless 00292 we have a do-nothing one to always use as the base. */ 00293 00294 void 00295 null_cleanup (void *arg) 00296 { 00297 }