| 1 | /* libunwind - a platform-independent unwind library | 
|---|
| 2 | Copyright (C) 2001-2004 Hewlett-Packard Co | 
|---|
| 3 | Contributed by David Mosberger-Tang <davidm@hpl.hp.com> | 
|---|
| 4 |  | 
|---|
| 5 | This file is part of libunwind. | 
|---|
| 6 |  | 
|---|
| 7 | Permission is hereby granted, free of charge, to any person obtaining | 
|---|
| 8 | a copy of this software and associated documentation files (the | 
|---|
| 9 | "Software"), to deal in the Software without restriction, including | 
|---|
| 10 | without limitation the rights to use, copy, modify, merge, publish, | 
|---|
| 11 | distribute, sublicense, and/or sell copies of the Software, and to | 
|---|
| 12 | permit persons to whom the Software is furnished to do so, subject to | 
|---|
| 13 | the following conditions: | 
|---|
| 14 |  | 
|---|
| 15 | The above copyright notice and this permission notice shall be | 
|---|
| 16 | included in all copies or substantial portions of the Software. | 
|---|
| 17 |  | 
|---|
| 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | 
|---|
| 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | 
|---|
| 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 
|---|
| 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | 
|---|
| 22 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | 
|---|
| 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | 
|---|
| 24 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */ | 
|---|
| 25 |  | 
|---|
| 26 | #define UNW_VERSION_MAJOR	1 | 
|---|
| 27 | #define UNW_VERSION_MINOR	3 | 
|---|
| 28 | #define 	2 | 
|---|
| 29 |  | 
|---|
| 30 | #define UNW_VERSION_CODE(maj,min)	(((maj) << 16) | (min)) | 
|---|
| 31 | #define UNW_VERSION	UNW_VERSION_CODE(UNW_VERSION_MAJOR, UNW_VERSION_MINOR) | 
|---|
| 32 |  | 
|---|
| 33 | #define UNW_PASTE2(x,y)	x##y | 
|---|
| 34 | #define UNW_PASTE(x,y)	UNW_PASTE2(x,y) | 
|---|
| 35 | #define UNW_OBJ(fn)	UNW_PASTE(UNW_PREFIX, fn) | 
|---|
| 36 | #define UNW_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_), fn) | 
|---|
| 37 |  | 
|---|
| 38 | #ifdef UNW_LOCAL_ONLY | 
|---|
| 39 | # define UNW_PREFIX	UNW_PASTE(UNW_PASTE(_UL,UNW_TARGET),_) | 
|---|
| 40 | #else /* !UNW_LOCAL_ONLY */ | 
|---|
| 41 | # define UNW_PREFIX	UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_) | 
|---|
| 42 | #endif /* !UNW_LOCAL_ONLY */ | 
|---|
| 43 |  | 
|---|
| 44 | /* Error codes.  The unwind routines return the *negated* values of | 
|---|
| 45 | these error codes on error and a non-negative value on success.  */ | 
|---|
| 46 | typedef enum | 
|---|
| 47 | { | 
|---|
| 48 | UNW_ESUCCESS = 0,		/* no error */ | 
|---|
| 49 | UNW_EUNSPEC,		/* unspecified (general) error */ | 
|---|
| 50 | UNW_ENOMEM,			/* out of memory */ | 
|---|
| 51 | UNW_EBADREG,		/* bad register number */ | 
|---|
| 52 | UNW_EREADONLYREG,		/* attempt to write read-only register */ | 
|---|
| 53 | UNW_ESTOPUNWIND,		/* stop unwinding */ | 
|---|
| 54 | UNW_EINVALIDIP,		/* invalid IP */ | 
|---|
| 55 | UNW_EBADFRAME,		/* bad frame */ | 
|---|
| 56 | UNW_EINVAL,			/* unsupported operation or bad value */ | 
|---|
| 57 | UNW_EBADVERSION,		/* unwind info has unsupported version */ | 
|---|
| 58 | UNW_ENOINFO			/* no unwind info found */ | 
|---|
| 59 | } | 
|---|
| 60 | unw_error_t; | 
|---|
| 61 |  | 
|---|
| 62 | /* The following enum defines the indices for a couple of | 
|---|
| 63 | (pseudo-)registers which have the same meaning across all | 
|---|
| 64 | platforms.  (RO) means read-only.  (RW) means read-write.  General | 
|---|
| 65 | registers (aka "integer registers") are expected to start with | 
|---|
| 66 | index 0.  The number of such registers is architecture-dependent. | 
|---|
| 67 | The remaining indices can be used as an architecture sees fit.  The | 
|---|
| 68 | last valid register index is given by UNW_REG_LAST.  */ | 
|---|
| 69 | typedef enum | 
|---|
| 70 | { | 
|---|
| 71 | UNW_REG_IP = UNW_TDEP_IP,		/* (rw) instruction pointer (pc) */ | 
|---|
| 72 | UNW_REG_SP = UNW_TDEP_SP,		/* (ro) stack pointer */ | 
|---|
| 73 | UNW_REG_EH = UNW_TDEP_EH,		/* (rw) exception-handling reg base */ | 
|---|
| 74 | UNW_REG_LAST = UNW_TDEP_LAST_REG | 
|---|
| 75 | } | 
|---|
| 76 | unw_frame_regnum_t; | 
|---|
| 77 |  | 
|---|
| 78 | /* Number of exception-handler argument registers: */ | 
|---|
| 79 | #define UNW_NUM_EH_REGS		UNW_TDEP_NUM_EH_REGS | 
|---|
| 80 |  | 
|---|
| 81 | typedef enum | 
|---|
| 82 | { | 
|---|
| 83 | UNW_CACHE_NONE,			/* no caching */ | 
|---|
| 84 | UNW_CACHE_GLOBAL,			/* shared global cache */ | 
|---|
| 85 | UNW_CACHE_PER_THREAD		/* per-thread caching */ | 
|---|
| 86 | } | 
|---|
| 87 | unw_caching_policy_t; | 
|---|
| 88 |  | 
|---|
| 89 | typedef enum | 
|---|
| 90 | { | 
|---|
| 91 | UNW_INIT_SIGNAL_FRAME = 1,          /* We know this is a signal frame */ | 
|---|
| 92 | } | 
|---|
| 93 | unw_init_local2_flags_t; | 
|---|
| 94 |  | 
|---|
| 95 | typedef int unw_regnum_t; | 
|---|
| 96 |  | 
|---|
| 97 | /* The unwind cursor starts at the youngest (most deeply nested) frame | 
|---|
| 98 | and is used to track the frame state as the unwinder steps from | 
|---|
| 99 | frame to frame.  It is safe to make (shallow) copies of variables | 
|---|
| 100 | of this type.  */ | 
|---|
| 101 | typedef struct unw_cursor | 
|---|
| 102 | { | 
|---|
| 103 | unw_word_t opaque[UNW_TDEP_CURSOR_LEN]; | 
|---|
| 104 | } | 
|---|
| 105 | unw_cursor_t; | 
|---|
| 106 |  | 
|---|
| 107 | /* This type encapsulates the entire (preserved) machine-state.  */ | 
|---|
| 108 | typedef unw_tdep_context_t unw_context_t; | 
|---|
| 109 |  | 
|---|
| 110 | /* unw_getcontext() fills the unw_context_t pointed to by UC with the | 
|---|
| 111 | machine state as it exists at the call-site.  For implementation | 
|---|
| 112 | reasons, this needs to be a target-dependent macro.  It's easiest | 
|---|
| 113 | to think of unw_getcontext() as being identical to getcontext(). */ | 
|---|
| 114 | #define unw_getcontext(uc)		unw_tdep_getcontext(uc) | 
|---|
| 115 |  | 
|---|
| 116 | /* Return 1 if register number R is a floating-point register, zero | 
|---|
| 117 | otherwise. | 
|---|
| 118 | This routine is signal-safe.  */ | 
|---|
| 119 | #define unw_is_fpreg(r)			unw_tdep_is_fpreg(r) | 
|---|
| 120 |  | 
|---|
| 121 | typedef unw_tdep_fpreg_t unw_fpreg_t; | 
|---|
| 122 |  | 
|---|
| 123 | typedef struct unw_addr_space *unw_addr_space_t; | 
|---|
| 124 |  | 
|---|
| 125 | /* Each target may define it's own set of flags, but bits 0-15 are | 
|---|
| 126 | reserved for general libunwind-use.  */ | 
|---|
| 127 | #define UNW_PI_FLAG_FIRST_TDEP_BIT	16 | 
|---|
| 128 | /* The information comes from a .debug_frame section.  */ | 
|---|
| 129 | #define UNW_PI_FLAG_DEBUG_FRAME	32 | 
|---|
| 130 |  | 
|---|
| 131 | typedef struct unw_proc_info | 
|---|
| 132 | { | 
|---|
| 133 | unw_word_t start_ip;	/* first IP covered by this procedure */ | 
|---|
| 134 | unw_word_t end_ip;		/* first IP NOT covered by this procedure */ | 
|---|
| 135 | #if defined(NEED_LAST_IP) | 
|---|
| 136 | unw_word_t last_ip;		/* first IP that could begin another procedure */ | 
|---|
| 137 | #endif | 
|---|
| 138 | unw_word_t lsda;		/* address of lang.-spec. data area (if any) */ | 
|---|
| 139 | unw_word_t handler;		/* optional personality routine */ | 
|---|
| 140 | unw_word_t gp;		/* global-pointer value for this procedure */ | 
|---|
| 141 | unw_word_t flags;		/* misc. flags */ | 
|---|
| 142 |  | 
|---|
| 143 | int format;			/* unwind-info format (arch-specific) */ | 
|---|
| 144 | int unwind_info_size;	/* size of the information (if applicable) */ | 
|---|
| 145 | void *unwind_info;		/* unwind-info (arch-specific) */ | 
|---|
| 146 | unw_tdep_proc_info_t ;	/* target-dependent auxiliary proc-info */ | 
|---|
| 147 | } | 
|---|
| 148 | unw_proc_info_t; | 
|---|
| 149 |  | 
|---|
| 150 | typedef int (*unw_reg_states_callback)(void *token, | 
|---|
| 151 | void *reg_states_data, | 
|---|
| 152 | size_t reg_states_data_size, | 
|---|
| 153 | unw_word_t start_ip, unw_word_t end_ip); | 
|---|
| 154 |  | 
|---|
| 155 | /* These are backend callback routines that provide access to the | 
|---|
| 156 | state of a "remote" process.  This can be used, for example, to | 
|---|
| 157 | unwind another process through the ptrace() interface.  */ | 
|---|
| 158 | typedef struct unw_accessors | 
|---|
| 159 | { | 
|---|
| 160 | /* Look up the unwind info associated with instruction-pointer IP. | 
|---|
| 161 | On success, the routine fills in the PROC_INFO structure.  */ | 
|---|
| 162 | int (*find_proc_info) (unw_addr_space_t, unw_word_t, unw_proc_info_t *, | 
|---|
| 163 | int, void *); | 
|---|
| 164 |  | 
|---|
| 165 | /* Release any resources (e.g., memory) that were allocated for | 
|---|
| 166 | the unwind info returned in by a previous call to | 
|---|
| 167 | find_proc_info() with NEED_UNWIND_INFO set to 1.  */ | 
|---|
| 168 | void (*put_unwind_info) (unw_addr_space_t, unw_proc_info_t *, void *); | 
|---|
| 169 |  | 
|---|
| 170 | /* Return the list-head of the dynamically registered unwind | 
|---|
| 171 | info.  */ | 
|---|
| 172 | int (*get_dyn_info_list_addr) (unw_addr_space_t, unw_word_t *, void *); | 
|---|
| 173 |  | 
|---|
| 174 | /* Access aligned word at address ADDR.  The value is returned | 
|---|
| 175 | according to the endianness of the host (e.g., if the host is | 
|---|
| 176 | little-endian and the target is big-endian, access_mem() needs | 
|---|
| 177 | to byte-swap the value before returning it).  */ | 
|---|
| 178 | int (*access_mem) (unw_addr_space_t, unw_word_t, unw_word_t *, int, | 
|---|
| 179 | void *); | 
|---|
| 180 |  | 
|---|
| 181 | /* Access register number REG at address ADDR.  */ | 
|---|
| 182 | int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *, int, | 
|---|
| 183 | void *); | 
|---|
| 184 |  | 
|---|
| 185 | /* Access register number REG at address ADDR.  */ | 
|---|
| 186 | int (*access_fpreg) (unw_addr_space_t, unw_regnum_t, | 
|---|
| 187 | unw_fpreg_t *, int, void *); | 
|---|
| 188 |  | 
|---|
| 189 | int (*resume) (unw_addr_space_t, unw_cursor_t *, void *); | 
|---|
| 190 |  | 
|---|
| 191 | /* Optional call back to obtain the name of a (static) procedure. | 
|---|
| 192 | Dynamically generated procedures are handled automatically by | 
|---|
| 193 | libunwind.  This callback is optional and may be set to | 
|---|
| 194 | NULL.  */ | 
|---|
| 195 | int (*get_proc_name) (unw_addr_space_t, unw_word_t, char *, size_t, | 
|---|
| 196 | unw_word_t *, void *); | 
|---|
| 197 | } | 
|---|
| 198 | unw_accessors_t; | 
|---|
| 199 |  | 
|---|
| 200 | typedef enum unw_save_loc_type | 
|---|
| 201 | { | 
|---|
| 202 | UNW_SLT_NONE,	/* register is not saved ("not an l-value") */ | 
|---|
| 203 | UNW_SLT_MEMORY,	/* register has been saved in memory */ | 
|---|
| 204 | UNW_SLT_REG		/* register has been saved in (another) register */ | 
|---|
| 205 | } | 
|---|
| 206 | unw_save_loc_type_t; | 
|---|
| 207 |  | 
|---|
| 208 | typedef struct unw_save_loc | 
|---|
| 209 | { | 
|---|
| 210 | unw_save_loc_type_t type; | 
|---|
| 211 | union | 
|---|
| 212 | { | 
|---|
| 213 | unw_word_t addr;	/* valid if type==UNW_SLT_MEMORY */ | 
|---|
| 214 | unw_regnum_t regnum;	/* valid if type==UNW_SLT_REG */ | 
|---|
| 215 | } | 
|---|
| 216 | u; | 
|---|
| 217 | unw_tdep_save_loc_t ;	/* target-dependent additional information */ | 
|---|
| 218 | } | 
|---|
| 219 | unw_save_loc_t; | 
|---|
| 220 |  | 
|---|
| 221 | /* These routines work both for local and remote unwinding.  */ | 
|---|
| 222 |  | 
|---|
| 223 | #define unw_local_addr_space	UNW_OBJ(local_addr_space) | 
|---|
| 224 | #define unw_create_addr_space	UNW_OBJ(create_addr_space) | 
|---|
| 225 | #define unw_destroy_addr_space	UNW_OBJ(destroy_addr_space) | 
|---|
| 226 | #define unw_get_accessors	UNW_ARCH_OBJ(get_accessors) | 
|---|
| 227 | #define unw_get_accessors_int	UNW_ARCH_OBJ(get_accessors_int) | 
|---|
| 228 | #define unw_init_local		UNW_OBJ(init_local) | 
|---|
| 229 | #define unw_init_local2	        UNW_OBJ(init_local2) | 
|---|
| 230 | #define unw_init_remote		UNW_OBJ(init_remote) | 
|---|
| 231 | #define unw_step		UNW_OBJ(step) | 
|---|
| 232 | #define unw_resume		UNW_OBJ(resume) | 
|---|
| 233 | #define unw_get_proc_info	UNW_OBJ(get_proc_info) | 
|---|
| 234 | #define unw_get_proc_info_by_ip	UNW_OBJ(get_proc_info_by_ip) | 
|---|
| 235 | #define unw_reg_states_iterate  UNW_OBJ(reg_states_iterate) | 
|---|
| 236 | #define unw_apply_reg_state     UNW_OBJ(apply_reg_state) | 
|---|
| 237 | #define unw_get_reg		UNW_OBJ(get_reg) | 
|---|
| 238 | #define unw_set_reg		UNW_OBJ(set_reg) | 
|---|
| 239 | #define unw_get_fpreg		UNW_OBJ(get_fpreg) | 
|---|
| 240 | #define unw_set_fpreg		UNW_OBJ(set_fpreg) | 
|---|
| 241 | #define unw_get_save_loc	UNW_OBJ(get_save_loc) | 
|---|
| 242 | #define unw_is_signal_frame	UNW_OBJ(is_signal_frame) | 
|---|
| 243 | #define unw_handle_signal_frame	UNW_OBJ(handle_signal_frame) | 
|---|
| 244 | #define unw_get_proc_name	UNW_OBJ(get_proc_name) | 
|---|
| 245 | #define unw_set_caching_policy	UNW_OBJ(set_caching_policy) | 
|---|
| 246 | #define unw_set_cache_size	UNW_OBJ(set_cache_size) | 
|---|
| 247 | #define unw_regname		UNW_ARCH_OBJ(regname) | 
|---|
| 248 | #define unw_flush_cache		UNW_ARCH_OBJ(flush_cache) | 
|---|
| 249 | #define unw_strerror		UNW_ARCH_OBJ(strerror) | 
|---|
| 250 |  | 
|---|
| 251 | extern unw_addr_space_t unw_create_addr_space (unw_accessors_t *, int); | 
|---|
| 252 | extern void unw_destroy_addr_space (unw_addr_space_t); | 
|---|
| 253 | extern unw_accessors_t *unw_get_accessors (unw_addr_space_t); | 
|---|
| 254 | extern unw_accessors_t *unw_get_accessors_int (unw_addr_space_t); | 
|---|
| 255 | extern void unw_flush_cache (unw_addr_space_t, unw_word_t, unw_word_t); | 
|---|
| 256 | extern int unw_set_caching_policy (unw_addr_space_t, unw_caching_policy_t); | 
|---|
| 257 | extern int unw_set_cache_size (unw_addr_space_t, size_t, int); | 
|---|
| 258 | extern const char *unw_regname (unw_regnum_t); | 
|---|
| 259 |  | 
|---|
| 260 | extern int unw_init_local (unw_cursor_t *, unw_context_t *); | 
|---|
| 261 | extern int unw_init_local2 (unw_cursor_t *, unw_context_t *, int); | 
|---|
| 262 | extern int unw_init_remote (unw_cursor_t *, unw_addr_space_t, void *); | 
|---|
| 263 | extern int unw_step (unw_cursor_t *); | 
|---|
| 264 | extern int unw_resume (unw_cursor_t *); | 
|---|
| 265 | extern int unw_get_proc_info (unw_cursor_t *, unw_proc_info_t *); | 
|---|
| 266 | extern int unw_get_proc_info_by_ip (unw_addr_space_t, unw_word_t, | 
|---|
| 267 | unw_proc_info_t *, void *); | 
|---|
| 268 | extern int unw_reg_states_iterate (unw_cursor_t *, unw_reg_states_callback, void *); | 
|---|
| 269 | extern int unw_apply_reg_state (unw_cursor_t *, void *); | 
|---|
| 270 | extern int unw_get_reg (unw_cursor_t *, int, unw_word_t *); | 
|---|
| 271 | extern int unw_set_reg (unw_cursor_t *, int, unw_word_t); | 
|---|
| 272 | extern int unw_get_fpreg (unw_cursor_t *, int, unw_fpreg_t *); | 
|---|
| 273 | extern int unw_set_fpreg (unw_cursor_t *, int, unw_fpreg_t); | 
|---|
| 274 | extern int unw_get_save_loc (unw_cursor_t *, int, unw_save_loc_t *); | 
|---|
| 275 | extern int unw_is_signal_frame (unw_cursor_t *); | 
|---|
| 276 | extern int unw_handle_signal_frame (unw_cursor_t *); | 
|---|
| 277 | extern int unw_get_proc_name (unw_cursor_t *, char *, size_t, unw_word_t *); | 
|---|
| 278 | extern const char *unw_strerror (int); | 
|---|
| 279 | extern int unw_backtrace (void **, int); | 
|---|
| 280 |  | 
|---|
| 281 | extern unw_addr_space_t unw_local_addr_space; | 
|---|
| 282 |  | 
|---|