1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 // 8 // Implements gcc extensions to the C++ ABI Exception Handling Level 1. 9 // 10 //===----------------------------------------------------------------------===// 11 12 #include <inttypes.h> 13 #include <stdbool.h> 14 #include <stdint.h> 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 19 #include "config.h" 20 #include "libunwind_ext.h" 21 #include "libunwind.h" 22 #include "Unwind-EHABI.h" 23 #include "unwind.h" 24 25 #if defined(_AIX) 26 #include <sys/debug.h> 27 #endif 28 29 #if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS) 30 31 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) 32 #define PRIVATE_1 private_[0] 33 #elif defined(_LIBUNWIND_ARM_EHABI) 34 #define PRIVATE_1 unwinder_cache.reserved1 35 #else 36 #define PRIVATE_1 private_1 37 #endif 38 39 /// Called by __cxa_rethrow(). 40 _LIBUNWIND_EXPORT _Unwind_Reason_Code 41 _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) { 42 _LIBUNWIND_TRACE_API( 43 "_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%" PRIdPTR, 44 (void *)exception_object, (intptr_t)exception_object->PRIVATE_1); 45 46 // If this is non-forced and a stopping place was found, then this is a 47 // re-throw. 48 // Call _Unwind_RaiseException() as if this was a new exception 49 if (exception_object->PRIVATE_1 == 0) { 50 return _Unwind_RaiseException(exception_object); 51 // Will return if there is no catch clause, so that __cxa_rethrow can call 52 // std::terminate(). 53 } 54 55 // Call through to _Unwind_Resume() which distinguishes between forced and 56 // regular exceptions. 57 _Unwind_Resume(exception_object); 58 _LIBUNWIND_ABORT("_Unwind_Resume_or_Rethrow() called _Unwind_RaiseException()" 59 " which unexpectedly returned"); 60 } 61 62 /// Called by personality handler during phase 2 to get base address for data 63 /// relative encodings. 64 _LIBUNWIND_EXPORT uintptr_t 65 _Unwind_GetDataRelBase(struct _Unwind_Context *context) { 66 _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", (void *)context); 67 #if defined(_AIX) 68 return unw_get_data_rel_base((unw_cursor_t *)context); 69 #else 70 (void)context; 71 _LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented"); 72 #endif 73 } 74 75 /// Called by personality handler during phase 2 to get base address for text 76 /// relative encodings. 77 _LIBUNWIND_EXPORT uintptr_t 78 _Unwind_GetTextRelBase(struct _Unwind_Context *context) { 79 (void)context; 80 _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", (void *)context); 81 _LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented"); 82 } 83 84 85 /// Scans unwind information to find the function that contains the 86 /// specified code address "pc". 87 _LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) { 88 _LIBUNWIND_TRACE_API("_Unwind_FindEnclosingFunction(pc=%p)", pc); 89 #if defined(_AIX) 90 if (pc == NULL) 91 return NULL; 92 93 // Get the start address of the enclosing function from the function's 94 // traceback table. 95 uint32_t *p = (uint32_t *)pc; 96 97 // Keep looking forward until a word of 0 is found. The traceback 98 // table starts at the following word. 99 while (*p) 100 ++p; 101 struct tbtable *TBTable = (struct tbtable *)(p + 1); 102 103 // Get the address of the traceback table extension. 104 p = (uint32_t *)&TBTable->tb_ext; 105 106 // Skip field parminfo if it exists. 107 if (TBTable->tb.fixedparms || TBTable->tb.floatparms) 108 ++p; 109 110 if (TBTable->tb.has_tboff) 111 // *p contains the offset from the function start to traceback table. 112 return (void *)((uintptr_t)TBTable - *p - sizeof(uint32_t)); 113 return NULL; 114 #else 115 // This is slow, but works. 116 // We create an unwind cursor then alter the IP to be pc 117 unw_cursor_t cursor; 118 unw_context_t uc; 119 unw_proc_info_t info; 120 __unw_getcontext(&uc); 121 __unw_init_local(&cursor, &uc); 122 __unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(intptr_t)pc); 123 if (__unw_get_proc_info(&cursor, &info) == UNW_ESUCCESS) 124 return (void *)(intptr_t) info.start_ip; 125 else 126 return NULL; 127 #endif 128 } 129 130 /// Walk every frame and call trace function at each one. If trace function 131 /// returns anything other than _URC_NO_REASON, then walk is terminated. 132 _LIBUNWIND_EXPORT _Unwind_Reason_Code 133 _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) { 134 unw_cursor_t cursor; 135 unw_context_t uc; 136 __unw_getcontext(&uc); 137 __unw_init_local(&cursor, &uc); 138 139 _LIBUNWIND_TRACE_API("_Unwind_Backtrace(callback=%p)", 140 (void *)(uintptr_t)callback); 141 142 #if defined(_LIBUNWIND_ARM_EHABI) 143 // Create a mock exception object for force unwinding. 144 _Unwind_Exception ex; 145 memset(&ex, '\0', sizeof(ex)); 146 memcpy(&ex.exception_class, "CLNGUNW", sizeof(ex.exception_class)); 147 #endif 148 149 // walk each frame 150 while (true) { 151 _Unwind_Reason_Code result; 152 153 #if !defined(_LIBUNWIND_ARM_EHABI) 154 // ask libunwind to get next frame (skip over first frame which is 155 // _Unwind_Backtrace()) 156 if (__unw_step(&cursor) <= 0) { 157 _LIBUNWIND_TRACE_UNWINDING(" _backtrace: ended because cursor reached " 158 "bottom of stack, returning %d", 159 _URC_END_OF_STACK); 160 return _URC_END_OF_STACK; 161 } 162 #else 163 // Get the information for this frame. 164 unw_proc_info_t frameInfo; 165 if (__unw_get_proc_info(&cursor, &frameInfo) != UNW_ESUCCESS) { 166 return _URC_END_OF_STACK; 167 } 168 169 // Update the pr_cache in the mock exception object. 170 uint32_t *unwindInfo = (uint32_t *)frameInfo.unwind_info; 171 ex.pr_cache.fnstart = frameInfo.start_ip; 172 ex.pr_cache.ehtp = (_Unwind_EHT_Header *) unwindInfo; 173 ex.pr_cache.additional= frameInfo.flags; 174 175 struct _Unwind_Context *context = (struct _Unwind_Context *)&cursor; 176 // Get and call the personality function to unwind the frame. 177 _Unwind_Personality_Fn handler = (_Unwind_Personality_Fn)frameInfo.handler; 178 if (handler == NULL) { 179 return _URC_END_OF_STACK; 180 } 181 if (handler(_US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND, &ex, context) != 182 _URC_CONTINUE_UNWIND) { 183 return _URC_END_OF_STACK; 184 } 185 #endif // defined(_LIBUNWIND_ARM_EHABI) 186 187 // debugging 188 if (_LIBUNWIND_TRACING_UNWINDING) { 189 char functionName[512]; 190 unw_proc_info_t frame; 191 unw_word_t offset; 192 __unw_get_proc_name(&cursor, functionName, 512, &offset); 193 __unw_get_proc_info(&cursor, &frame); 194 _LIBUNWIND_TRACE_UNWINDING( 195 " _backtrace: start_ip=0x%" PRIxPTR ", func=%s, lsda=0x%" PRIxPTR ", context=%p", 196 frame.start_ip, functionName, frame.lsda, 197 (void *)&cursor); 198 } 199 200 // call trace function with this frame 201 result = (*callback)((struct _Unwind_Context *)(&cursor), ref); 202 if (result != _URC_NO_REASON) { 203 _LIBUNWIND_TRACE_UNWINDING( 204 " _backtrace: ended because callback returned %d", result); 205 return result; 206 } 207 } 208 } 209 #ifdef __arm__ 210 /* Preserve legacy libgcc (pre r318024) ARM ABI mistake */ 211 __sym_compat(_Unwind_Backtrace, _Unwind_Backtrace, GCC_3.3); 212 #endif 213 214 215 /// Find DWARF unwind info for an address 'pc' in some function. 216 _LIBUNWIND_EXPORT const void *_Unwind_Find_FDE(const void *pc, 217 struct dwarf_eh_bases *bases) { 218 // This is slow, but works. 219 // We create an unwind cursor then alter the IP to be pc 220 unw_cursor_t cursor; 221 unw_context_t uc; 222 unw_proc_info_t info; 223 __unw_getcontext(&uc); 224 __unw_init_local(&cursor, &uc); 225 __unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(intptr_t)pc); 226 __unw_get_proc_info(&cursor, &info); 227 bases->tbase = (uintptr_t)info.extra; 228 bases->dbase = 0; // dbase not used on Mac OS X 229 bases->func = (uintptr_t)info.start_ip; 230 _LIBUNWIND_TRACE_API("_Unwind_Find_FDE(pc=%p) => %p", pc, 231 (void *)(intptr_t) info.unwind_info); 232 return (void *)(intptr_t) info.unwind_info; 233 } 234 235 /// Returns the CFA (call frame area, or stack pointer at start of function) 236 /// for the current context. 237 _LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) { 238 unw_cursor_t *cursor = (unw_cursor_t *)context; 239 unw_word_t result; 240 __unw_get_reg(cursor, UNW_REG_SP, &result); 241 _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p) => 0x%" PRIxPTR, 242 (void *)context, result); 243 return (uintptr_t)result; 244 } 245 246 247 /// Called by personality handler during phase 2 to get instruction pointer. 248 /// ipBefore is a boolean that says if IP is already adjusted to be the call 249 /// site address. Normally IP is the return address. 250 _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, 251 int *ipBefore) { 252 _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p)", (void *)context); 253 int isSignalFrame = __unw_is_signal_frame((unw_cursor_t *)context); 254 // Negative means some kind of error (probably UNW_ENOINFO), but we have no 255 // good way to report that, and this maintains backward compatibility with the 256 // implementation that hard-coded zero in every case, even signal frames. 257 if (isSignalFrame <= 0) 258 *ipBefore = 0; 259 else 260 *ipBefore = 1; 261 return _Unwind_GetIP(context); 262 } 263 264 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 265 266 #if defined(__FreeBSD__) 267 268 // Based on LLVM's lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp 269 // and XXX should be fixed to be alignment-safe. 270 static void processFDE(const char *addr, bool isDeregister) { 271 uint64_t length; 272 while ((length = *((const uint32_t *)addr)) != 0) { 273 const char *p = addr + 4; 274 if (length == 0xffffffff) { 275 length = *((const uint64_t *)p); 276 p += 8; 277 } 278 uint32_t offset = *((const uint32_t *)p); 279 if (offset != 0) { 280 if (isDeregister) 281 __unw_remove_dynamic_fde((unw_word_t)(uintptr_t)addr); 282 else 283 __unw_add_dynamic_fde((unw_word_t)(uintptr_t)addr); 284 } 285 addr = p + length; 286 } 287 } 288 289 /// Called by programs with dynamic code generators that want to register 290 /// dynamically generated FDEs, with a libgcc-compatible API. 291 292 _LIBUNWIND_EXPORT void __register_frame(const void *addr) { 293 _LIBUNWIND_TRACE_API("__register_frame(%p)", addr); 294 processFDE(addr, false); 295 } 296 297 /// Called by programs with dynamic code generators that want to unregister 298 /// dynamically generated FDEs, with a libgcc-compatible API. 299 _LIBUNWIND_EXPORT void __deregister_frame(const void *addr) { 300 _LIBUNWIND_TRACE_API("__deregister_frame(%p)", addr); 301 processFDE(addr, true); 302 } 303 304 #else // defined(__FreeBSD__) 305 306 /// Called by programs with dynamic code generators that want 307 /// to register a dynamically generated FDE. 308 /// This function has existed on Mac OS X since 10.4, but 309 /// was broken until 10.6. 310 _LIBUNWIND_EXPORT void __register_frame(const void *fde) { 311 _LIBUNWIND_TRACE_API("__register_frame(%p)", fde); 312 __unw_add_dynamic_fde((unw_word_t)(uintptr_t)fde); 313 } 314 315 316 /// Called by programs with dynamic code generators that want 317 /// to unregister a dynamically generated FDE. 318 /// This function has existed on Mac OS X since 10.4, but 319 /// was broken until 10.6. 320 _LIBUNWIND_EXPORT void __deregister_frame(const void *fde) { 321 _LIBUNWIND_TRACE_API("__deregister_frame(%p)", fde); 322 __unw_remove_dynamic_fde((unw_word_t)(uintptr_t)fde); 323 } 324 325 #endif // defined(__FreeBSD__) 326 327 // The following register/deregister functions are gcc extensions. 328 // They have existed on Mac OS X, but have never worked because Mac OS X 329 // before 10.6 used keymgr to track known FDEs, but these functions 330 // never got updated to use keymgr. 331 // For now, we implement these as do-nothing functions to keep any existing 332 // applications working. We also add the not in 10.6 symbol so that nwe 333 // application won't be able to use them. 334 335 #if defined(_LIBUNWIND_SUPPORT_FRAME_APIS) 336 _LIBUNWIND_EXPORT void __register_frame_info_bases(const void *fde, void *ob, 337 void *tb, void *db) { 338 (void)fde; 339 (void)ob; 340 (void)tb; 341 (void)db; 342 _LIBUNWIND_TRACE_API("__register_frame_info_bases(%p,%p, %p, %p)", 343 fde, ob, tb, db); 344 // do nothing, this function never worked in Mac OS X 345 } 346 347 _LIBUNWIND_EXPORT void __register_frame_info(const void *fde, void *ob) { 348 (void)fde; 349 (void)ob; 350 _LIBUNWIND_TRACE_API("__register_frame_info(%p, %p)", fde, ob); 351 // do nothing, this function never worked in Mac OS X 352 } 353 354 _LIBUNWIND_EXPORT void __register_frame_info_table_bases(const void *fde, 355 void *ob, void *tb, 356 void *db) { 357 (void)fde; 358 (void)ob; 359 (void)tb; 360 (void)db; 361 _LIBUNWIND_TRACE_API("__register_frame_info_table_bases" 362 "(%p,%p, %p, %p)", fde, ob, tb, db); 363 // do nothing, this function never worked in Mac OS X 364 } 365 366 _LIBUNWIND_EXPORT void __register_frame_info_table(const void *fde, void *ob) { 367 (void)fde; 368 (void)ob; 369 _LIBUNWIND_TRACE_API("__register_frame_info_table(%p, %p)", fde, ob); 370 // do nothing, this function never worked in Mac OS X 371 } 372 373 _LIBUNWIND_EXPORT void __register_frame_table(const void *fde) { 374 (void)fde; 375 _LIBUNWIND_TRACE_API("__register_frame_table(%p)", fde); 376 // do nothing, this function never worked in Mac OS X 377 } 378 379 _LIBUNWIND_EXPORT void *__deregister_frame_info(const void *fde) { 380 (void)fde; 381 _LIBUNWIND_TRACE_API("__deregister_frame_info(%p)", fde); 382 // do nothing, this function never worked in Mac OS X 383 return NULL; 384 } 385 386 _LIBUNWIND_EXPORT void *__deregister_frame_info_bases(const void *fde) { 387 (void)fde; 388 _LIBUNWIND_TRACE_API("__deregister_frame_info_bases(%p)", fde); 389 // do nothing, this function never worked in Mac OS X 390 return NULL; 391 } 392 #endif // defined(_LIBUNWIND_SUPPORT_FRAME_APIS) 393 394 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 395 396 #endif // defined(_LIBUNWIND_BUILD_ZERO_COST_APIS) 397