Coverage Report

Created: 2025-08-28 06:28

/src/llvm-project-18.1.8.src/libcxxabi/src/cxa_exception_storage.cpp
Line
Count
Source (jump to first uncovered line)
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
//  This file implements the storage for the "Caught Exception Stack"
9
//  https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#cxx-exc-stack
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "cxa_exception.h"
14
15
#include <__threading_support>
16
17
#if defined(_LIBCXXABI_HAS_NO_THREADS)
18
19
namespace __cxxabiv1 {
20
extern "C" {
21
    static __cxa_eh_globals eh_globals;
22
    __cxa_eh_globals *__cxa_get_globals() { return &eh_globals; }
23
    __cxa_eh_globals *__cxa_get_globals_fast() { return &eh_globals; }
24
} // extern "C"
25
} // namespace __cxxabiv1
26
27
#elif defined(HAS_THREAD_LOCAL)
28
29
namespace __cxxabiv1 {
30
namespace {
31
    __cxa_eh_globals *__globals() {
32
        static thread_local __cxa_eh_globals eh_globals;
33
        return &eh_globals;
34
    }
35
} // namespace
36
37
extern "C" {
38
    __cxa_eh_globals *__cxa_get_globals() { return __globals(); }
39
    __cxa_eh_globals *__cxa_get_globals_fast() { return __globals(); }
40
} // extern "C"
41
} // namespace __cxxabiv1
42
43
#else
44
45
#include "abort_message.h"
46
#include "fallback_malloc.h"
47
48
#if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB)
49
#pragma comment(lib, "pthread")
50
#endif
51
52
//  In general, we treat all threading errors as fatal.
53
//  We cannot call std::terminate() because that will in turn
54
//  call __cxa_get_globals() and cause infinite recursion.
55
56
namespace __cxxabiv1 {
57
namespace {
58
    std::__libcpp_tls_key key_;
59
    std::__libcpp_exec_once_flag flag_ = _LIBCPP_EXEC_ONCE_INITIALIZER;
60
61
271
    void _LIBCPP_TLS_DESTRUCTOR_CC destruct_(void *p) {
62
271
        __free_with_fallback(p);
63
271
        if (0 != std::__libcpp_tls_set(key_, NULL))
64
0
            abort_message("cannot zero out thread value for __cxa_get_globals()");
65
271
    }
66
67
77
    void construct_() {
68
77
        if (0 != std::__libcpp_tls_create(&key_, destruct_))
69
0
            abort_message("cannot create thread specific key for __cxa_get_globals()");
70
77
    }
71
} // namespace
72
73
extern "C" {
74
4.37M
    __cxa_eh_globals *__cxa_get_globals() {
75
        // Try to get the globals for this thread
76
4.37M
        __cxa_eh_globals *retVal = __cxa_get_globals_fast();
77
78
        // If this is the first time we've been asked for these globals, create them
79
4.37M
        if (NULL == retVal) {
80
348
            retVal = static_cast<__cxa_eh_globals*>(
81
348
                __calloc_with_fallback(1, sizeof(__cxa_eh_globals)));
82
348
            if (NULL == retVal)
83
0
                abort_message("cannot allocate __cxa_eh_globals");
84
348
            if (0 != std::__libcpp_tls_set(key_, retVal))
85
0
               abort_message("std::__libcpp_tls_set failure in __cxa_get_globals()");
86
348
        }
87
4.37M
        return retVal;
88
4.37M
    }
89
90
    // Note that this implementation will reliably return NULL if not
91
    // preceded by a call to __cxa_get_globals().  This is an extension
92
    // to the Itanium ABI and is taken advantage of in several places in
93
    // libc++abi.
94
6.58M
    __cxa_eh_globals *__cxa_get_globals_fast() {
95
        // First time through, create the key.
96
6.58M
        if (0 != std::__libcpp_execute_once(&flag_, construct_))
97
0
            abort_message("execute once failure in __cxa_get_globals_fast()");
98
6.58M
        return static_cast<__cxa_eh_globals*>(std::__libcpp_tls_get(key_));
99
6.58M
    }
100
} // extern "C"
101
} // namespace __cxxabiv1
102
103
#endif