1 /**
2 * Copyright (c) 2021-2022 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 #include "include/tooling/debug_inf.h"
16
17 //
18 // Debuge interface for native tools(perf, libunwind).
19 //
20
21 namespace panda::tooling {
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25
26 enum CodeAction {
27 CODE_NOACTION = 0,
28 CODE_ADDED,
29 CODE_REMOVE,
30 };
31
32 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
33 struct PCodeItem {
34 std::atomic<PCodeItem *> next_;
35 PCodeItem *prev_;
36 const uint8_t *code_base_;
37 uint64_t code_size_;
38 uint64_t timestamp_;
39 };
40
41 struct PCodeMetaInfo {
42 uint32_t version_ = 1;
43 uint32_t action_ = CODE_NOACTION;
44 PCodeItem *relevent_item_ = nullptr;
45 std::atomic<PCodeItem *> head_ {nullptr};
46
47 // Panda-specific fields
48 // NOLINTNEXTLINE(readability-magic-numbers)
49 uint8_t magic_[8] = {'P', 'a', 'n', 'd', 'a', 'r', 't', '1'};
50 uint32_t flags_ = 0;
51 uint32_t size_meta_info_ = sizeof(PCodeMetaInfo);
52 uint32_t size_codeitem_ = sizeof(PCodeItem);
53 std::atomic_uint32_t update_lock_ {0};
54 uint64_t timestamp_ = 1;
55 };
56
57 // perf currently use g_jitDebugDescriptor and g_dexDebugDescriptor
58 // to find the jit code item and dexfiles.
59 // for using the variable interface, we doesn't change the name in panda
60 // NOLINTNEXTLINE(readability-identifier-naming, fuchsia-statically-constructed-objects)
61 PCodeMetaInfo g_jitDebugDescriptor;
62 // NOLINTNEXTLINE(readability-identifier-naming, fuchsia-statically-constructed-objects)
63 PCodeMetaInfo g_dexDebugDescriptor;
64
65 #ifdef __cplusplus
66 } // extern "C"
67 #endif
68
69 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects)
70 std::map<const std::string, PCodeItem *> DebugInf::aex_item_map;
71 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects)
72 panda::os::memory::Mutex DebugInf::jit_item_lock;
73 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects)
74 panda::os::memory::Mutex DebugInf::aex_item_lock;
75
AddCodeMetaInfo(const panda_file::File * file)76 void DebugInf::AddCodeMetaInfo(const panda_file::File *file)
77 {
78 panda::os::memory::LockHolder lock(aex_item_lock);
79 ASSERT(file != nullptr);
80 auto it = aex_item_map.find(file->GetFilename());
81 if (it != aex_item_map.end()) {
82 return;
83 }
84
85 PCodeItem *item = AddCodeMetaInfoImpl(&g_dexDebugDescriptor, {file->GetBase(), file->GetHeader()->file_size});
86 aex_item_map.emplace(file->GetFilename(), item);
87 }
88
DelCodeMetaInfo(const panda_file::File * file)89 void DebugInf::DelCodeMetaInfo(const panda_file::File *file)
90 {
91 panda::os::memory::LockHolder lock(aex_item_lock);
92 ASSERT(file != nullptr);
93 auto it = aex_item_map.find(file->GetFilename());
94 if (it == aex_item_map.end()) {
95 return;
96 }
97
98 DelCodeMetaInfoImpl(&g_dexDebugDescriptor, file);
99 }
100
Lock(PCodeMetaInfo * mi)101 void DebugInf::Lock(PCodeMetaInfo *mi)
102 {
103 // Atomic with relaxed order reason: data race with update_lock_ with no synchronization or ordering constraints
104 // imposed on other reads or writes
105 mi->update_lock_.fetch_add(1, std::memory_order_relaxed);
106 std::atomic_thread_fence(std::memory_order_release);
107 }
108
UnLock(PCodeMetaInfo * mi)109 void DebugInf::UnLock(PCodeMetaInfo *mi)
110 {
111 std::atomic_thread_fence(std::memory_order_release);
112 // Atomic with relaxed order reason: data race with update_lock_ with no synchronization or ordering constraints
113 // imposed on other reads or writes
114 mi->update_lock_.fetch_add(1, std::memory_order_relaxed);
115 }
116
AddCodeMetaInfoImpl(PCodeMetaInfo * metaInfo,Span<const uint8_t> inss)117 PCodeItem *DebugInf::AddCodeMetaInfoImpl(PCodeMetaInfo *metaInfo, [[maybe_unused]] Span<const uint8_t> inss)
118 {
119 uint64_t timestamp = std::max(metaInfo->timestamp_ + 1, panda::time::GetCurrentTimeInNanos());
120
121 // Atomic with relaxed order reason: data race with metaInfo with no synchronization or ordering constraints imposed
122 // on other reads or writes
123 auto *head = metaInfo->head_.load(std::memory_order_relaxed);
124
125 auto *codeItem = new PCodeItem;
126 codeItem->code_base_ = inss.begin();
127 codeItem->code_size_ = inss.Size();
128 codeItem->prev_ = nullptr;
129 // Atomic with relaxed order reason: data race with codeItem with no synchronization or ordering constraints imposed
130 // on other reads or writes
131 codeItem->next_.store(head, std::memory_order_relaxed);
132 codeItem->timestamp_ = timestamp;
133
134 // lock
135 Lock(metaInfo);
136 if (head != nullptr) {
137 head->prev_ = codeItem;
138 }
139
140 // Atomic with relaxed order reason: data race with metaInfo with no synchronization or ordering constraints imposed
141 // on other reads or writes
142 metaInfo->head_.store(codeItem, std::memory_order_relaxed);
143 metaInfo->relevent_item_ = codeItem;
144 metaInfo->action_ = CODE_ADDED;
145
146 // unlock
147 UnLock(metaInfo);
148
149 return codeItem;
150 }
151
DelCodeMetaInfoImpl(PCodeMetaInfo * metaInfo,const panda_file::File * file)152 void DebugInf::DelCodeMetaInfoImpl(PCodeMetaInfo *metaInfo, const panda_file::File *file)
153 {
154 PCodeItem *codeItem = aex_item_map[file->GetFilename()];
155 ASSERT(codeItem != nullptr);
156 uint64_t timestamp = std::max(metaInfo->timestamp_ + 1, panda::time::GetCurrentTimeInNanos());
157 // lock
158 Lock(metaInfo);
159
160 // Atomic with relaxed order reason: data race with codeItem with no synchronization or ordering constraints imposed
161 // on other reads or writes
162 auto next = codeItem->next_.load(std::memory_order_relaxed);
163 if (codeItem->prev_ != nullptr) {
164 // Atomic with relaxed order reason: data race with codeItem with no synchronization or ordering constraints
165 // imposed on other reads or writes
166 codeItem->prev_->next_.store(next, std::memory_order_relaxed);
167 } else {
168 // Atomic with relaxed order reason: data race with metaInfo with no synchronization or ordering constraints
169 // imposed on other reads or writes
170 metaInfo->head_.store(next, std::memory_order_relaxed);
171 }
172
173 if (next != nullptr) {
174 next->prev_ = codeItem->prev_;
175 }
176
177 metaInfo->relevent_item_ = codeItem;
178 metaInfo->action_ = CODE_REMOVE;
179 metaInfo->timestamp_ = timestamp;
180
181 // unlock
182 UnLock(metaInfo);
183 }
184 } // namespace panda::tooling
185