• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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