• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef THREAD_CONTEXT_H
17 #define THREAD_CONTEXT_H
18 
19 #include <atomic>
20 #include <cstdint>
21 #include <condition_variable>
22 #include <csignal>
23 #include <mutex>
24 #include <nocopyable.h>
25 #include <string>
26 #include <vector>
27 
28 #include "dfx_define.h"
29 #include "dfx_maps.h"
30 #include "dfx_regs.h"
31 
32 namespace OHOS {
33 namespace HiviewDFX {
34 enum ThreadContextStatus : int32_t {
35     CONTEXT_UNUSED = -1,
36     CONTEXT_READY = -2,
37 };
38 
39 struct ThreadContext {
40     std::atomic<int32_t> tid {ThreadContextStatus::CONTEXT_UNUSED};
41     // for protecting ctx, shared between threads
42     std::mutex mtx;
43     // the thread should be suspended while unwinding
44     // blocked in the signal handler of target thread
45     std::condition_variable cv;
46     // store unwind context
47     ucontext_t* ctx {nullptr};
48     // stack range
49     uintptr_t stackBottom;
50     uintptr_t stackTop;
51 #if defined(__aarch64__)
52     // unwind in signal handler by fp
53     uintptr_t pcs[DEFAULT_MAX_LOCAL_FRAME_NUM] {0};
54 #endif
55     std::atomic<size_t> frameSz {0};
56     // first stack pointer
57     uintptr_t firstFrameSp;
58 
~ThreadContextThreadContext59     ~ThreadContext()
60     {
61         std::unique_lock<std::mutex> lock(mtx);
62         if (ctx != nullptr) {
63             delete ctx;
64             ctx = nullptr;
65         }
66     };
67 };
68 
69 class LocalThreadContext {
70 public:
71     static LocalThreadContext& GetInstance();
72 
73     bool GetStackRange(int32_t tid, uintptr_t& stackBottom, uintptr_t& stackTop);
74     std::shared_ptr<ThreadContext> CollectThreadContext(int32_t tid);
75     std::shared_ptr<ThreadContext> GetThreadContext(int32_t tid);
76     void ReleaseThread(int32_t tid);
77     void CleanUp();
78 
79 private:
80     LocalThreadContext() = default;
81     DISALLOW_COPY_AND_MOVE(LocalThreadContext);
82 
83     bool SignalRequestThread(int32_t tid, ThreadContext* ctx);
84 
85 private:
86     std::mutex localMutex_;
87 };
88 
89 constexpr int STACK_BUFFER_SIZE = 64 * 1024;
90 enum SyncStatus : int32_t {
91     INIT = -1,
92     WAIT_CTX = 0,
93     COPY_START,
94     COPY_SUCCESS,
95     COPY_FAILED,
96 };
97 
98 class LocalThreadContextMix {
99 public:
100     LocalThreadContextMix(const LocalThreadContextMix&) = delete;
101     LocalThreadContextMix& operator=(const LocalThreadContextMix&) = delete;
102     static LocalThreadContextMix& GetInstance();
103     void ReleaseCollectThreadContext();
104     bool CollectThreadContext(int32_t tid);
105     bool CheckStatusValidate(int status, int32_t tid);
106     bool GetSelfStackRangeInSignal();
107     void CopyRegister(void *context);
108     void CopyStackBuf();
109     void SetRegister(std::shared_ptr<DfxRegs> regs);
110     void SetStackRang(uintptr_t stackTop, uintptr_t stackBottom);
111     int GetMapByPc(uintptr_t pc, std::shared_ptr<DfxMap>& map) const;
112     int FindUnwindTable(uintptr_t pc, UnwindTableInfo& outTableInfo) const;
113     int AccessMem(uintptr_t addr, uintptr_t *val);
114     std::shared_ptr<DfxMaps> GetMaps() const;
115 
116 private:
117     LocalThreadContextMix() = default;
118     ~LocalThreadContextMix() = default;
119     bool SignalRequestThread(int32_t tid);
120     void StartCollectThreadContext(int32_t tid);
121 
122 private:
123     std::mutex mtx_;
124     std::condition_variable cv_;
125     uintptr_t pc_ {0};
126     uintptr_t sp_ {0};
127     uintptr_t fp_ {0};
128     uintptr_t lr_ {0};
129     uintptr_t stackBottom_ {0};
130     uintptr_t stackTop_ {0};
131     std::vector<uint8_t> stackBuf_;
132     int32_t tid_ = -1;
133     int status_ = SyncStatus::INIT;
134     std::shared_ptr<DfxMaps> maps_ = nullptr;
135 };
136 } // namespace Dfx
137 } // namespace OHOS
138 #endif
139