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