xref: /aosp_15_r20/system/unwinding/libunwindstack/GlobalDebugImpl.h (revision eb293b8f56ee8303637c5595cfcdeef8039e85c6)
1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*eb293b8fSAndroid Build Coastguard Worker  *
4*eb293b8fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*eb293b8fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*eb293b8fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*eb293b8fSAndroid Build Coastguard Worker  *
8*eb293b8fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*eb293b8fSAndroid Build Coastguard Worker  *
10*eb293b8fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*eb293b8fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*eb293b8fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*eb293b8fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*eb293b8fSAndroid Build Coastguard Worker  * limitations under the License.
15*eb293b8fSAndroid Build Coastguard Worker  */
16*eb293b8fSAndroid Build Coastguard Worker 
17*eb293b8fSAndroid Build Coastguard Worker #pragma once
18*eb293b8fSAndroid Build Coastguard Worker 
19*eb293b8fSAndroid Build Coastguard Worker #include <stdint.h>
20*eb293b8fSAndroid Build Coastguard Worker #include <string.h>
21*eb293b8fSAndroid Build Coastguard Worker #include <sys/mman.h>
22*eb293b8fSAndroid Build Coastguard Worker 
23*eb293b8fSAndroid Build Coastguard Worker #include <memory>
24*eb293b8fSAndroid Build Coastguard Worker #include <vector>
25*eb293b8fSAndroid Build Coastguard Worker 
26*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Global.h>
27*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Maps.h>
28*eb293b8fSAndroid Build Coastguard Worker 
29*eb293b8fSAndroid Build Coastguard Worker #include "Check.h"
30*eb293b8fSAndroid Build Coastguard Worker #include "GlobalDebugInterface.h"
31*eb293b8fSAndroid Build Coastguard Worker #include "MemoryCache.h"
32*eb293b8fSAndroid Build Coastguard Worker #include "MemoryRange.h"
33*eb293b8fSAndroid Build Coastguard Worker 
34*eb293b8fSAndroid Build Coastguard Worker // This implements the JIT Compilation Interface.
35*eb293b8fSAndroid Build Coastguard Worker // See https://sourceware.org/gdb/onlinedocs/gdb/JIT-Interface.html
36*eb293b8fSAndroid Build Coastguard Worker //
37*eb293b8fSAndroid Build Coastguard Worker // We use it to get in-memory ELF files created by the ART compiler,
38*eb293b8fSAndroid Build Coastguard Worker // but we also use it to get list of DEX files used by the runtime.
39*eb293b8fSAndroid Build Coastguard Worker 
40*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
41*eb293b8fSAndroid Build Coastguard Worker 
42*eb293b8fSAndroid Build Coastguard Worker // Implementation templated for ELF/DEX and for different architectures.
43*eb293b8fSAndroid Build Coastguard Worker template <typename Symfile, typename Uintptr_T, typename Uint64_T>
44*eb293b8fSAndroid Build Coastguard Worker class GlobalDebugImpl : public GlobalDebugInterface<Symfile>, public Global {
45*eb293b8fSAndroid Build Coastguard Worker  public:
46*eb293b8fSAndroid Build Coastguard Worker   static constexpr int kMaxRaceRetries = 16;
47*eb293b8fSAndroid Build Coastguard Worker   static constexpr int kMaxHeadRetries = 16;
48*eb293b8fSAndroid Build Coastguard Worker   static constexpr uint8_t kMagic[8] = {'A', 'n', 'd', 'r', 'o', 'i', 'd', '2'};
49*eb293b8fSAndroid Build Coastguard Worker 
50*eb293b8fSAndroid Build Coastguard Worker   struct JITCodeEntry {
51*eb293b8fSAndroid Build Coastguard Worker     Uintptr_T next;
52*eb293b8fSAndroid Build Coastguard Worker     Uintptr_T prev;
53*eb293b8fSAndroid Build Coastguard Worker     Uintptr_T symfile_addr;
54*eb293b8fSAndroid Build Coastguard Worker     Uint64_T symfile_size;
55*eb293b8fSAndroid Build Coastguard Worker     // Android-specific fields:
56*eb293b8fSAndroid Build Coastguard Worker     Uint64_T timestamp;
57*eb293b8fSAndroid Build Coastguard Worker     uint32_t seqlock;
58*eb293b8fSAndroid Build Coastguard Worker   };
59*eb293b8fSAndroid Build Coastguard Worker 
60*eb293b8fSAndroid Build Coastguard Worker   static constexpr size_t kSizeOfCodeEntryV1 = offsetof(JITCodeEntry, timestamp);
61*eb293b8fSAndroid Build Coastguard Worker   static constexpr size_t kSizeOfCodeEntryV2 = sizeof(JITCodeEntry);
62*eb293b8fSAndroid Build Coastguard Worker 
63*eb293b8fSAndroid Build Coastguard Worker   struct JITDescriptor {
64*eb293b8fSAndroid Build Coastguard Worker     uint32_t version;
65*eb293b8fSAndroid Build Coastguard Worker     uint32_t action_flag;
66*eb293b8fSAndroid Build Coastguard Worker     Uintptr_T relevant_entry;
67*eb293b8fSAndroid Build Coastguard Worker     Uintptr_T first_entry;
68*eb293b8fSAndroid Build Coastguard Worker     // Android-specific fields:
69*eb293b8fSAndroid Build Coastguard Worker     uint8_t magic[8];
70*eb293b8fSAndroid Build Coastguard Worker     uint32_t flags;
71*eb293b8fSAndroid Build Coastguard Worker     uint32_t sizeof_descriptor;
72*eb293b8fSAndroid Build Coastguard Worker     uint32_t sizeof_entry;
73*eb293b8fSAndroid Build Coastguard Worker     uint32_t seqlock;
74*eb293b8fSAndroid Build Coastguard Worker     Uint64_T timestamp;
75*eb293b8fSAndroid Build Coastguard Worker   };
76*eb293b8fSAndroid Build Coastguard Worker 
77*eb293b8fSAndroid Build Coastguard Worker   static constexpr size_t kSizeOfDescriptorV1 = offsetof(JITDescriptor, magic);
78*eb293b8fSAndroid Build Coastguard Worker   static constexpr size_t kSizeOfDescriptorV2 = sizeof(JITDescriptor);
79*eb293b8fSAndroid Build Coastguard Worker 
80*eb293b8fSAndroid Build Coastguard Worker   // This uniquely identifies entry in presence of concurrent modifications.
81*eb293b8fSAndroid Build Coastguard Worker   // Each (address,seqlock) pair is unique for each newly created JIT entry.
82*eb293b8fSAndroid Build Coastguard Worker   struct UID {
83*eb293b8fSAndroid Build Coastguard Worker     uint64_t address;  // Address of JITCodeEntry in memory.
84*eb293b8fSAndroid Build Coastguard Worker     uint32_t seqlock;  // This servers as "version" for the given address.
85*eb293b8fSAndroid Build Coastguard Worker 
86*eb293b8fSAndroid Build Coastguard Worker     bool operator<(const UID& other) const {
87*eb293b8fSAndroid Build Coastguard Worker       return std::tie(address, seqlock) < std::tie(other.address, other.seqlock);
88*eb293b8fSAndroid Build Coastguard Worker     }
89*eb293b8fSAndroid Build Coastguard Worker   };
90*eb293b8fSAndroid Build Coastguard Worker 
GlobalDebugImpl(ArchEnum arch,std::shared_ptr<Memory> & memory,std::vector<std::string> & search_libs,const char * global_variable_name)91*eb293b8fSAndroid Build Coastguard Worker   GlobalDebugImpl(ArchEnum arch, std::shared_ptr<Memory>& memory,
92*eb293b8fSAndroid Build Coastguard Worker                   std::vector<std::string>& search_libs, const char* global_variable_name)
93*eb293b8fSAndroid Build Coastguard Worker       : Global(memory, search_libs), global_variable_name_(global_variable_name) {
94*eb293b8fSAndroid Build Coastguard Worker     SetArch(arch);
95*eb293b8fSAndroid Build Coastguard Worker   }
96*eb293b8fSAndroid Build Coastguard Worker 
ReadDescriptor(uint64_t addr)97*eb293b8fSAndroid Build Coastguard Worker   bool ReadDescriptor(uint64_t addr) {
98*eb293b8fSAndroid Build Coastguard Worker     JITDescriptor desc{};
99*eb293b8fSAndroid Build Coastguard Worker     // Try to read the full descriptor including Android-specific fields.
100*eb293b8fSAndroid Build Coastguard Worker     if (!this->memory_->ReadFully(addr, &desc, kSizeOfDescriptorV2)) {
101*eb293b8fSAndroid Build Coastguard Worker       // Fallback to just the minimal descriptor.
102*eb293b8fSAndroid Build Coastguard Worker       // This will make the magic check below fail.
103*eb293b8fSAndroid Build Coastguard Worker       if (!this->memory_->ReadFully(addr, &desc, kSizeOfDescriptorV1)) {
104*eb293b8fSAndroid Build Coastguard Worker         return false;
105*eb293b8fSAndroid Build Coastguard Worker       }
106*eb293b8fSAndroid Build Coastguard Worker     }
107*eb293b8fSAndroid Build Coastguard Worker 
108*eb293b8fSAndroid Build Coastguard Worker     if (desc.version != 1 || desc.first_entry == 0) {
109*eb293b8fSAndroid Build Coastguard Worker       // Either unknown version, or no jit entries.
110*eb293b8fSAndroid Build Coastguard Worker       return false;
111*eb293b8fSAndroid Build Coastguard Worker     }
112*eb293b8fSAndroid Build Coastguard Worker 
113*eb293b8fSAndroid Build Coastguard Worker     // Check if there are extra Android-specific fields.
114*eb293b8fSAndroid Build Coastguard Worker     if (memcmp(desc.magic, kMagic, sizeof(kMagic)) == 0) {
115*eb293b8fSAndroid Build Coastguard Worker       jit_entry_size_ = kSizeOfCodeEntryV2;
116*eb293b8fSAndroid Build Coastguard Worker       seqlock_offset_ = offsetof(JITCodeEntry, seqlock);
117*eb293b8fSAndroid Build Coastguard Worker     } else {
118*eb293b8fSAndroid Build Coastguard Worker       jit_entry_size_ = kSizeOfCodeEntryV1;
119*eb293b8fSAndroid Build Coastguard Worker       seqlock_offset_ = 0;
120*eb293b8fSAndroid Build Coastguard Worker     }
121*eb293b8fSAndroid Build Coastguard Worker     descriptor_addr_ = addr;
122*eb293b8fSAndroid Build Coastguard Worker     return true;
123*eb293b8fSAndroid Build Coastguard Worker   }
124*eb293b8fSAndroid Build Coastguard Worker 
ProcessArch()125*eb293b8fSAndroid Build Coastguard Worker   void ProcessArch() {}
126*eb293b8fSAndroid Build Coastguard Worker 
ReadVariableData(uint64_t ptr)127*eb293b8fSAndroid Build Coastguard Worker   bool ReadVariableData(uint64_t ptr) { return ReadDescriptor(ptr); }
128*eb293b8fSAndroid Build Coastguard Worker 
129*eb293b8fSAndroid Build Coastguard Worker   // Invoke callback for all symfiles that contain the given PC.
130*eb293b8fSAndroid Build Coastguard Worker   // Returns true if any callback returns true (which also aborts the iteration).
131*eb293b8fSAndroid Build Coastguard Worker   template <typename Callback /* (Symfile*) -> bool */>
ForEachSymfile(Maps * maps,uint64_t pc,Callback callback)132*eb293b8fSAndroid Build Coastguard Worker   bool ForEachSymfile(Maps* maps, uint64_t pc, Callback callback) {
133*eb293b8fSAndroid Build Coastguard Worker     // Use a single lock, this object should be used so infrequently that
134*eb293b8fSAndroid Build Coastguard Worker     // a fine grain lock is unnecessary.
135*eb293b8fSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> guard(lock_);
136*eb293b8fSAndroid Build Coastguard Worker     if (descriptor_addr_ == 0) {
137*eb293b8fSAndroid Build Coastguard Worker       FindAndReadVariable(maps, global_variable_name_);
138*eb293b8fSAndroid Build Coastguard Worker       if (descriptor_addr_ == 0) {
139*eb293b8fSAndroid Build Coastguard Worker         return false;
140*eb293b8fSAndroid Build Coastguard Worker       }
141*eb293b8fSAndroid Build Coastguard Worker     }
142*eb293b8fSAndroid Build Coastguard Worker 
143*eb293b8fSAndroid Build Coastguard Worker     // Try to find the entry in already loaded symbol files.
144*eb293b8fSAndroid Build Coastguard Worker     for (auto& it : entries_) {
145*eb293b8fSAndroid Build Coastguard Worker       Symfile* symfile = it.second.get();
146*eb293b8fSAndroid Build Coastguard Worker       // Check seqlock to make sure that entry is still valid (it may be very old).
147*eb293b8fSAndroid Build Coastguard Worker       if (symfile->IsValidPc(pc) && CheckSeqlock(it.first) && callback(symfile)) {
148*eb293b8fSAndroid Build Coastguard Worker         return true;
149*eb293b8fSAndroid Build Coastguard Worker       }
150*eb293b8fSAndroid Build Coastguard Worker     }
151*eb293b8fSAndroid Build Coastguard Worker 
152*eb293b8fSAndroid Build Coastguard Worker     // Update all entries and retry.
153*eb293b8fSAndroid Build Coastguard Worker     ReadAllEntries(maps);
154*eb293b8fSAndroid Build Coastguard Worker     for (auto& it : entries_) {
155*eb293b8fSAndroid Build Coastguard Worker       Symfile* symfile = it.second.get();
156*eb293b8fSAndroid Build Coastguard Worker       // Note that the entry could become invalid since the ReadAllEntries above,
157*eb293b8fSAndroid Build Coastguard Worker       // but that is ok.  We don't want to fail or refresh the entries yet again.
158*eb293b8fSAndroid Build Coastguard Worker       // This is as if we found the entry in time and it became invalid after return.
159*eb293b8fSAndroid Build Coastguard Worker       // This is relevant when ART moves/packs JIT entries. That is, the entry is
160*eb293b8fSAndroid Build Coastguard Worker       // technically deleted, but only because it was copied into merged uber-entry.
161*eb293b8fSAndroid Build Coastguard Worker       // So the JIT method is still alive and the deleted data is still correct.
162*eb293b8fSAndroid Build Coastguard Worker       if (symfile->IsValidPc(pc) && callback(symfile)) {
163*eb293b8fSAndroid Build Coastguard Worker         return true;
164*eb293b8fSAndroid Build Coastguard Worker       }
165*eb293b8fSAndroid Build Coastguard Worker     }
166*eb293b8fSAndroid Build Coastguard Worker 
167*eb293b8fSAndroid Build Coastguard Worker     return false;
168*eb293b8fSAndroid Build Coastguard Worker   }
169*eb293b8fSAndroid Build Coastguard Worker 
GetFunctionName(Maps * maps,uint64_t pc,SharedString * name,uint64_t * offset)170*eb293b8fSAndroid Build Coastguard Worker   bool GetFunctionName(Maps* maps, uint64_t pc, SharedString* name, uint64_t* offset) {
171*eb293b8fSAndroid Build Coastguard Worker     // NB: If symfiles overlap in PC ranges, this will check all of them.
172*eb293b8fSAndroid Build Coastguard Worker     return ForEachSymfile(maps, pc, [pc, name, offset](Symfile* file) {
173*eb293b8fSAndroid Build Coastguard Worker       return file->GetFunctionName(pc, name, offset);
174*eb293b8fSAndroid Build Coastguard Worker     });
175*eb293b8fSAndroid Build Coastguard Worker   }
176*eb293b8fSAndroid Build Coastguard Worker 
Find(Maps * maps,uint64_t pc)177*eb293b8fSAndroid Build Coastguard Worker   Symfile* Find(Maps* maps, uint64_t pc) {
178*eb293b8fSAndroid Build Coastguard Worker     // NB: If symfiles overlap in PC ranges (which can happen for both ELF and DEX),
179*eb293b8fSAndroid Build Coastguard Worker     // this will check all of them and return one that also has a matching function.
180*eb293b8fSAndroid Build Coastguard Worker     Symfile* result = nullptr;
181*eb293b8fSAndroid Build Coastguard Worker     bool found = ForEachSymfile(maps, pc, [pc, &result](Symfile* file) {
182*eb293b8fSAndroid Build Coastguard Worker       result = file;
183*eb293b8fSAndroid Build Coastguard Worker       SharedString name;
184*eb293b8fSAndroid Build Coastguard Worker       uint64_t offset;
185*eb293b8fSAndroid Build Coastguard Worker       return file->GetFunctionName(pc, &name, &offset);
186*eb293b8fSAndroid Build Coastguard Worker     });
187*eb293b8fSAndroid Build Coastguard Worker     if (found) {
188*eb293b8fSAndroid Build Coastguard Worker       return result;  // Found symfile with symbol that also matches the PC.
189*eb293b8fSAndroid Build Coastguard Worker     }
190*eb293b8fSAndroid Build Coastguard Worker     // There is no matching symbol, so return any symfile for which the PC is valid.
191*eb293b8fSAndroid Build Coastguard Worker     // This is a useful fallback for tests, which often have symfiles with no functions.
192*eb293b8fSAndroid Build Coastguard Worker     return result;
193*eb293b8fSAndroid Build Coastguard Worker   }
194*eb293b8fSAndroid Build Coastguard Worker 
195*eb293b8fSAndroid Build Coastguard Worker   // Read all entries from the process and cache them locally.
196*eb293b8fSAndroid Build Coastguard Worker   // The linked list might be concurrently modified. We detect races and retry.
ReadAllEntries(Maps * maps)197*eb293b8fSAndroid Build Coastguard Worker   bool ReadAllEntries(Maps* maps) {
198*eb293b8fSAndroid Build Coastguard Worker     for (int i = 0; i < kMaxRaceRetries; i++) {
199*eb293b8fSAndroid Build Coastguard Worker       bool race = false;
200*eb293b8fSAndroid Build Coastguard Worker       if (!ReadAllEntries(maps, &race)) {
201*eb293b8fSAndroid Build Coastguard Worker         if (race) {
202*eb293b8fSAndroid Build Coastguard Worker           continue;  // Retry due to concurrent modification of the linked list.
203*eb293b8fSAndroid Build Coastguard Worker         }
204*eb293b8fSAndroid Build Coastguard Worker         return false;  // Failed to read entries.
205*eb293b8fSAndroid Build Coastguard Worker       }
206*eb293b8fSAndroid Build Coastguard Worker       return true;  // Success.
207*eb293b8fSAndroid Build Coastguard Worker     }
208*eb293b8fSAndroid Build Coastguard Worker     return false;  // Too many retries.
209*eb293b8fSAndroid Build Coastguard Worker   }
210*eb293b8fSAndroid Build Coastguard Worker 
211*eb293b8fSAndroid Build Coastguard Worker   // Read all JIT entries while assuming there might be concurrent modifications.
212*eb293b8fSAndroid Build Coastguard Worker   // If there is a race, the method will fail and the caller should retry the call.
ReadAllEntries(Maps * maps,bool * race)213*eb293b8fSAndroid Build Coastguard Worker   bool ReadAllEntries(Maps* maps, bool* race) {
214*eb293b8fSAndroid Build Coastguard Worker     // New entries might be added while we iterate over the linked list.
215*eb293b8fSAndroid Build Coastguard Worker     // In particular, an entry could be effectively moved from end to start due to
216*eb293b8fSAndroid Build Coastguard Worker     // the ART repacking algorithm, which groups smaller entries into a big one.
217*eb293b8fSAndroid Build Coastguard Worker     // Therefore keep reading the most recent entries until we reach a fixed point.
218*eb293b8fSAndroid Build Coastguard Worker     std::map<UID, std::shared_ptr<Symfile>> entries;
219*eb293b8fSAndroid Build Coastguard Worker     for (size_t i = 0; i < kMaxHeadRetries; i++) {
220*eb293b8fSAndroid Build Coastguard Worker       size_t old_size = entries.size();
221*eb293b8fSAndroid Build Coastguard Worker       if (!ReadNewEntries(maps, &entries, race)) {
222*eb293b8fSAndroid Build Coastguard Worker         return false;
223*eb293b8fSAndroid Build Coastguard Worker       }
224*eb293b8fSAndroid Build Coastguard Worker       if (entries.size() == old_size) {
225*eb293b8fSAndroid Build Coastguard Worker         entries_.swap(entries);
226*eb293b8fSAndroid Build Coastguard Worker         return true;
227*eb293b8fSAndroid Build Coastguard Worker       }
228*eb293b8fSAndroid Build Coastguard Worker     }
229*eb293b8fSAndroid Build Coastguard Worker     return false;  // Too many retries.
230*eb293b8fSAndroid Build Coastguard Worker   }
231*eb293b8fSAndroid Build Coastguard Worker 
232*eb293b8fSAndroid Build Coastguard Worker   // Read new JIT entries (head of linked list) until we find one that we have seen before.
233*eb293b8fSAndroid Build Coastguard Worker   // This method uses seqlocks extensively to ensure safety in case of concurrent modifications.
ReadNewEntries(Maps * maps,std::map<UID,std::shared_ptr<Symfile>> * entries,bool * race)234*eb293b8fSAndroid Build Coastguard Worker   bool ReadNewEntries(Maps* maps, std::map<UID, std::shared_ptr<Symfile>>* entries, bool* race) {
235*eb293b8fSAndroid Build Coastguard Worker     // Read the address of the head entry in the linked list.
236*eb293b8fSAndroid Build Coastguard Worker     UID uid;
237*eb293b8fSAndroid Build Coastguard Worker     if (!ReadNextField(descriptor_addr_ + offsetof(JITDescriptor, first_entry), &uid, race)) {
238*eb293b8fSAndroid Build Coastguard Worker       return false;
239*eb293b8fSAndroid Build Coastguard Worker     }
240*eb293b8fSAndroid Build Coastguard Worker 
241*eb293b8fSAndroid Build Coastguard Worker     // Follow the linked list.
242*eb293b8fSAndroid Build Coastguard Worker     while (uid.address != 0) {
243*eb293b8fSAndroid Build Coastguard Worker       // Check if we have reached an already cached entry (we restart from head repeatedly).
244*eb293b8fSAndroid Build Coastguard Worker       if (entries->contains(uid)) {
245*eb293b8fSAndroid Build Coastguard Worker         return true;
246*eb293b8fSAndroid Build Coastguard Worker       }
247*eb293b8fSAndroid Build Coastguard Worker 
248*eb293b8fSAndroid Build Coastguard Worker       // Read the entry.
249*eb293b8fSAndroid Build Coastguard Worker       JITCodeEntry data{};
250*eb293b8fSAndroid Build Coastguard Worker       if (!memory_->ReadFully(uid.address, &data, jit_entry_size_)) {
251*eb293b8fSAndroid Build Coastguard Worker         return false;
252*eb293b8fSAndroid Build Coastguard Worker       }
253*eb293b8fSAndroid Build Coastguard Worker       data.symfile_addr = StripAddressTag(data.symfile_addr);
254*eb293b8fSAndroid Build Coastguard Worker 
255*eb293b8fSAndroid Build Coastguard Worker       // Check the seqlock to verify the symfile_addr and symfile_size.
256*eb293b8fSAndroid Build Coastguard Worker       if (!CheckSeqlock(uid, race)) {
257*eb293b8fSAndroid Build Coastguard Worker         return false;
258*eb293b8fSAndroid Build Coastguard Worker       }
259*eb293b8fSAndroid Build Coastguard Worker 
260*eb293b8fSAndroid Build Coastguard Worker       // Copy and load the symfile.
261*eb293b8fSAndroid Build Coastguard Worker       auto it = entries_.find(uid);
262*eb293b8fSAndroid Build Coastguard Worker       if (it != entries_.end()) {
263*eb293b8fSAndroid Build Coastguard Worker         // The symfile was already loaded - just copy the reference.
264*eb293b8fSAndroid Build Coastguard Worker         entries->emplace(uid, it->second);
265*eb293b8fSAndroid Build Coastguard Worker       } else if (data.symfile_addr != 0) {
266*eb293b8fSAndroid Build Coastguard Worker         std::shared_ptr<Symfile> symfile;
267*eb293b8fSAndroid Build Coastguard Worker         bool ok = this->Load(maps, memory_, data.symfile_addr, data.symfile_size.value, symfile);
268*eb293b8fSAndroid Build Coastguard Worker         // Check seqlock first because load can fail due to race (so we want to trigger retry).
269*eb293b8fSAndroid Build Coastguard Worker         // TODO: Extract the memory copy code before the load, so that it is immune to races.
270*eb293b8fSAndroid Build Coastguard Worker         if (!CheckSeqlock(uid, race)) {
271*eb293b8fSAndroid Build Coastguard Worker           return false;  // The ELF/DEX data was removed before we loaded it.
272*eb293b8fSAndroid Build Coastguard Worker         }
273*eb293b8fSAndroid Build Coastguard Worker         // Exclude symbol files that fail to load (but continue loading other files).
274*eb293b8fSAndroid Build Coastguard Worker         if (ok) {
275*eb293b8fSAndroid Build Coastguard Worker           entries->emplace(uid, symfile);
276*eb293b8fSAndroid Build Coastguard Worker         }
277*eb293b8fSAndroid Build Coastguard Worker       }
278*eb293b8fSAndroid Build Coastguard Worker 
279*eb293b8fSAndroid Build Coastguard Worker       // Go to next entry.
280*eb293b8fSAndroid Build Coastguard Worker       UID next_uid;
281*eb293b8fSAndroid Build Coastguard Worker       if (!ReadNextField(uid.address + offsetof(JITCodeEntry, next), &next_uid, race)) {
282*eb293b8fSAndroid Build Coastguard Worker         return false;  // The next pointer was modified while we were reading it.
283*eb293b8fSAndroid Build Coastguard Worker       }
284*eb293b8fSAndroid Build Coastguard Worker       if (!CheckSeqlock(uid, race)) {
285*eb293b8fSAndroid Build Coastguard Worker         return false;  // This entry was deleted before we moved to the next one.
286*eb293b8fSAndroid Build Coastguard Worker       }
287*eb293b8fSAndroid Build Coastguard Worker       uid = next_uid;
288*eb293b8fSAndroid Build Coastguard Worker     }
289*eb293b8fSAndroid Build Coastguard Worker 
290*eb293b8fSAndroid Build Coastguard Worker     return true;
291*eb293b8fSAndroid Build Coastguard Worker   }
292*eb293b8fSAndroid Build Coastguard Worker 
293*eb293b8fSAndroid Build Coastguard Worker   // Read the address and seqlock of entry from the next field of linked list.
294*eb293b8fSAndroid Build Coastguard Worker   // This is non-trivial since they need to be consistent (as if we read both atomically).
295*eb293b8fSAndroid Build Coastguard Worker   //
296*eb293b8fSAndroid Build Coastguard Worker   // We're reading pointers, which can point at heap-allocated structures (the
297*eb293b8fSAndroid Build Coastguard Worker   // case for the __dex_debug_descriptor pointers at the time of writing).
298*eb293b8fSAndroid Build Coastguard Worker   // On 64 bit systems, the target process might have top-byte heap pointer
299*eb293b8fSAndroid Build Coastguard Worker   // tagging enabled, so we need to mask out the tag. We also know that the
300*eb293b8fSAndroid Build Coastguard Worker   // address must point to userspace, so the top byte of the address must be
301*eb293b8fSAndroid Build Coastguard Worker   // zero on both x64 and aarch64 without tagging. Therefore the masking can be
302*eb293b8fSAndroid Build Coastguard Worker   // done unconditionally.
ReadNextField(uint64_t next_field_addr,UID * uid,bool * race)303*eb293b8fSAndroid Build Coastguard Worker   bool ReadNextField(uint64_t next_field_addr, UID* uid, bool* race) {
304*eb293b8fSAndroid Build Coastguard Worker     Uintptr_T address[2]{0, 0};
305*eb293b8fSAndroid Build Coastguard Worker     uint32_t seqlock[2]{0, 0};
306*eb293b8fSAndroid Build Coastguard Worker     // Read all data twice: address[0], seqlock[0], address[1], seqlock[1].
307*eb293b8fSAndroid Build Coastguard Worker     for (int i = 0; i < 2; i++) {
308*eb293b8fSAndroid Build Coastguard Worker       std::atomic_thread_fence(std::memory_order_acquire);
309*eb293b8fSAndroid Build Coastguard Worker       if (!(memory_->ReadFully(next_field_addr, &address[i], sizeof(address[i])))) {
310*eb293b8fSAndroid Build Coastguard Worker         return false;
311*eb293b8fSAndroid Build Coastguard Worker       }
312*eb293b8fSAndroid Build Coastguard Worker       address[i] = StripAddressTag(address[i]);
313*eb293b8fSAndroid Build Coastguard Worker       if (seqlock_offset_ == 0) {
314*eb293b8fSAndroid Build Coastguard Worker         // There is no seqlock field.
315*eb293b8fSAndroid Build Coastguard Worker         *uid = UID{.address = address[0], .seqlock = 0};
316*eb293b8fSAndroid Build Coastguard Worker         return true;
317*eb293b8fSAndroid Build Coastguard Worker       }
318*eb293b8fSAndroid Build Coastguard Worker       if (address[i] != 0) {
319*eb293b8fSAndroid Build Coastguard Worker         std::atomic_thread_fence(std::memory_order_acquire);
320*eb293b8fSAndroid Build Coastguard Worker         if (!memory_->ReadFully(address[i] + seqlock_offset_, &seqlock[i], sizeof(seqlock[i]))) {
321*eb293b8fSAndroid Build Coastguard Worker           return false;
322*eb293b8fSAndroid Build Coastguard Worker         }
323*eb293b8fSAndroid Build Coastguard Worker       }
324*eb293b8fSAndroid Build Coastguard Worker     }
325*eb293b8fSAndroid Build Coastguard Worker     // Check that both reads returned identical values, and that the entry is live.
326*eb293b8fSAndroid Build Coastguard Worker     if (address[0] != address[1] || seqlock[0] != seqlock[1] || (seqlock[0] & 1) == 1) {
327*eb293b8fSAndroid Build Coastguard Worker       *race = true;
328*eb293b8fSAndroid Build Coastguard Worker       return false;
329*eb293b8fSAndroid Build Coastguard Worker     }
330*eb293b8fSAndroid Build Coastguard Worker     // Since address[1] is sandwiched between two seqlock reads, we know that
331*eb293b8fSAndroid Build Coastguard Worker     // at the time of address[1] read, the entry had the given seqlock value.
332*eb293b8fSAndroid Build Coastguard Worker     *uid = UID{.address = address[1], .seqlock = seqlock[1]};
333*eb293b8fSAndroid Build Coastguard Worker     return true;
334*eb293b8fSAndroid Build Coastguard Worker   }
335*eb293b8fSAndroid Build Coastguard Worker 
336*eb293b8fSAndroid Build Coastguard Worker   // Check that the given entry has not been deleted (or replaced by new entry at same address).
337*eb293b8fSAndroid Build Coastguard Worker   bool CheckSeqlock(UID uid, bool* race = nullptr) {
338*eb293b8fSAndroid Build Coastguard Worker     if (seqlock_offset_ == 0) {
339*eb293b8fSAndroid Build Coastguard Worker       // There is no seqlock field.
340*eb293b8fSAndroid Build Coastguard Worker       return true;
341*eb293b8fSAndroid Build Coastguard Worker     }
342*eb293b8fSAndroid Build Coastguard Worker     // This is required for memory synchronization if the we are working with local memory.
343*eb293b8fSAndroid Build Coastguard Worker     // For other types of memory (e.g. remote) this is no-op and has no significant effect.
344*eb293b8fSAndroid Build Coastguard Worker     std::atomic_thread_fence(std::memory_order_acquire);
345*eb293b8fSAndroid Build Coastguard Worker     uint32_t seen_seqlock;
346*eb293b8fSAndroid Build Coastguard Worker     if (!memory_->Read32(uid.address + seqlock_offset_, &seen_seqlock)) {
347*eb293b8fSAndroid Build Coastguard Worker       return false;
348*eb293b8fSAndroid Build Coastguard Worker     }
349*eb293b8fSAndroid Build Coastguard Worker     if (seen_seqlock != uid.seqlock) {
350*eb293b8fSAndroid Build Coastguard Worker       if (race != nullptr) {
351*eb293b8fSAndroid Build Coastguard Worker         *race = true;
352*eb293b8fSAndroid Build Coastguard Worker       }
353*eb293b8fSAndroid Build Coastguard Worker       return false;
354*eb293b8fSAndroid Build Coastguard Worker     }
355*eb293b8fSAndroid Build Coastguard Worker     return true;
356*eb293b8fSAndroid Build Coastguard Worker   }
357*eb293b8fSAndroid Build Coastguard Worker 
358*eb293b8fSAndroid Build Coastguard Worker   // AArch64 has Address tagging (aka Top Byte Ignore) feature, which is used by
359*eb293b8fSAndroid Build Coastguard Worker   // HWASAN and MTE to store metadata in the address. We need to remove the tag.
StripAddressTag(Uintptr_T addr)360*eb293b8fSAndroid Build Coastguard Worker   Uintptr_T StripAddressTag(Uintptr_T addr) {
361*eb293b8fSAndroid Build Coastguard Worker     if (arch() == ARCH_ARM64) {
362*eb293b8fSAndroid Build Coastguard Worker       // Make the value signed so it will be sign extended if necessary.
363*eb293b8fSAndroid Build Coastguard Worker       return static_cast<Uintptr_T>((static_cast<int64_t>(addr) << 8) >> 8);
364*eb293b8fSAndroid Build Coastguard Worker     }
365*eb293b8fSAndroid Build Coastguard Worker     return addr;
366*eb293b8fSAndroid Build Coastguard Worker   }
367*eb293b8fSAndroid Build Coastguard Worker 
368*eb293b8fSAndroid Build Coastguard Worker  private:
369*eb293b8fSAndroid Build Coastguard Worker   const char* global_variable_name_ = nullptr;
370*eb293b8fSAndroid Build Coastguard Worker   uint64_t descriptor_addr_ = 0;  // Non-zero if we have found (non-empty) descriptor.
371*eb293b8fSAndroid Build Coastguard Worker   uint32_t jit_entry_size_ = 0;
372*eb293b8fSAndroid Build Coastguard Worker   uint32_t seqlock_offset_ = 0;
373*eb293b8fSAndroid Build Coastguard Worker   std::map<UID, std::shared_ptr<Symfile>> entries_;  // Cached loaded entries.
374*eb293b8fSAndroid Build Coastguard Worker 
375*eb293b8fSAndroid Build Coastguard Worker   std::mutex lock_;
376*eb293b8fSAndroid Build Coastguard Worker };
377*eb293b8fSAndroid Build Coastguard Worker 
378*eb293b8fSAndroid Build Coastguard Worker // uint64_t values on x86 are not naturally aligned,
379*eb293b8fSAndroid Build Coastguard Worker // but uint64_t values on ARM are naturally aligned.
380*eb293b8fSAndroid Build Coastguard Worker struct Uint64_P {
381*eb293b8fSAndroid Build Coastguard Worker   uint64_t value;
382*eb293b8fSAndroid Build Coastguard Worker } __attribute__((packed));
383*eb293b8fSAndroid Build Coastguard Worker struct Uint64_A {
384*eb293b8fSAndroid Build Coastguard Worker   uint64_t value;
385*eb293b8fSAndroid Build Coastguard Worker } __attribute__((aligned(8)));
386*eb293b8fSAndroid Build Coastguard Worker 
387*eb293b8fSAndroid Build Coastguard Worker template <typename Symfile>
CreateGlobalDebugImpl(ArchEnum arch,std::shared_ptr<Memory> & memory,std::vector<std::string> search_libs,const char * global_variable_name)388*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<GlobalDebugInterface<Symfile>> CreateGlobalDebugImpl(
389*eb293b8fSAndroid Build Coastguard Worker     ArchEnum arch, std::shared_ptr<Memory>& memory, std::vector<std::string> search_libs,
390*eb293b8fSAndroid Build Coastguard Worker     const char* global_variable_name) {
391*eb293b8fSAndroid Build Coastguard Worker   CHECK(arch != ARCH_UNKNOWN);
392*eb293b8fSAndroid Build Coastguard Worker 
393*eb293b8fSAndroid Build Coastguard Worker   // The interface needs to see real-time changes in memory for synchronization with the
394*eb293b8fSAndroid Build Coastguard Worker   // concurrently running ART JIT compiler. Skip caching and read the memory directly.
395*eb293b8fSAndroid Build Coastguard Worker   std::shared_ptr<Memory> jit_memory;
396*eb293b8fSAndroid Build Coastguard Worker   MemoryCacheBase* cached_memory = memory->AsMemoryCacheBase();
397*eb293b8fSAndroid Build Coastguard Worker   if (cached_memory != nullptr) {
398*eb293b8fSAndroid Build Coastguard Worker     jit_memory = cached_memory->UnderlyingMemory();
399*eb293b8fSAndroid Build Coastguard Worker   } else {
400*eb293b8fSAndroid Build Coastguard Worker     jit_memory = memory;
401*eb293b8fSAndroid Build Coastguard Worker   }
402*eb293b8fSAndroid Build Coastguard Worker 
403*eb293b8fSAndroid Build Coastguard Worker   switch (arch) {
404*eb293b8fSAndroid Build Coastguard Worker     case ARCH_X86: {
405*eb293b8fSAndroid Build Coastguard Worker       using Impl = GlobalDebugImpl<Symfile, uint32_t, Uint64_P>;
406*eb293b8fSAndroid Build Coastguard Worker       static_assert(offsetof(typename Impl::JITCodeEntry, symfile_size) == 12, "layout");
407*eb293b8fSAndroid Build Coastguard Worker       static_assert(offsetof(typename Impl::JITCodeEntry, seqlock) == 28, "layout");
408*eb293b8fSAndroid Build Coastguard Worker       static_assert(sizeof(typename Impl::JITCodeEntry) == 32, "layout");
409*eb293b8fSAndroid Build Coastguard Worker       static_assert(sizeof(typename Impl::JITDescriptor) == 48, "layout");
410*eb293b8fSAndroid Build Coastguard Worker       return std::make_unique<Impl>(arch, jit_memory, search_libs, global_variable_name);
411*eb293b8fSAndroid Build Coastguard Worker     }
412*eb293b8fSAndroid Build Coastguard Worker     case ARCH_ARM: {
413*eb293b8fSAndroid Build Coastguard Worker       using Impl = GlobalDebugImpl<Symfile, uint32_t, Uint64_A>;
414*eb293b8fSAndroid Build Coastguard Worker       static_assert(offsetof(typename Impl::JITCodeEntry, symfile_size) == 16, "layout");
415*eb293b8fSAndroid Build Coastguard Worker       static_assert(offsetof(typename Impl::JITCodeEntry, seqlock) == 32, "layout");
416*eb293b8fSAndroid Build Coastguard Worker       static_assert(sizeof(typename Impl::JITCodeEntry) == 40, "layout");
417*eb293b8fSAndroid Build Coastguard Worker       static_assert(sizeof(typename Impl::JITDescriptor) == 48, "layout");
418*eb293b8fSAndroid Build Coastguard Worker       return std::make_unique<Impl>(arch, jit_memory, search_libs, global_variable_name);
419*eb293b8fSAndroid Build Coastguard Worker     }
420*eb293b8fSAndroid Build Coastguard Worker     case ARCH_ARM64:
421*eb293b8fSAndroid Build Coastguard Worker     case ARCH_X86_64:
422*eb293b8fSAndroid Build Coastguard Worker     case ARCH_RISCV64: {
423*eb293b8fSAndroid Build Coastguard Worker       using Impl = GlobalDebugImpl<Symfile, uint64_t, Uint64_A>;
424*eb293b8fSAndroid Build Coastguard Worker       static_assert(offsetof(typename Impl::JITCodeEntry, symfile_size) == 24, "layout");
425*eb293b8fSAndroid Build Coastguard Worker       static_assert(offsetof(typename Impl::JITCodeEntry, seqlock) == 40, "layout");
426*eb293b8fSAndroid Build Coastguard Worker       static_assert(sizeof(typename Impl::JITCodeEntry) == 48, "layout");
427*eb293b8fSAndroid Build Coastguard Worker       static_assert(sizeof(typename Impl::JITDescriptor) == 56, "layout");
428*eb293b8fSAndroid Build Coastguard Worker       return std::make_unique<Impl>(arch, jit_memory, search_libs, global_variable_name);
429*eb293b8fSAndroid Build Coastguard Worker     }
430*eb293b8fSAndroid Build Coastguard Worker     default:
431*eb293b8fSAndroid Build Coastguard Worker       abort();
432*eb293b8fSAndroid Build Coastguard Worker   }
433*eb293b8fSAndroid Build Coastguard Worker }
434*eb293b8fSAndroid Build Coastguard Worker 
435*eb293b8fSAndroid Build Coastguard Worker }  // namespace unwindstack
436