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