]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Plugins / DynamicLoader / POSIX-DYLD / DYLDRendezvous.cpp
1 //===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "lldb/Core/Module.h"
10 #include "lldb/Symbol/ObjectFile.h"
11 #include "lldb/Symbol/Symbol.h"
12 #include "lldb/Symbol/SymbolContext.h"
13 #include "lldb/Target/Platform.h"
14 #include "lldb/Target/Process.h"
15 #include "lldb/Target/Target.h"
16 #include "lldb/Utility/ArchSpec.h"
17 #include "lldb/Utility/Log.h"
18 #include "lldb/Utility/Status.h"
19
20 #include "llvm/Support/Path.h"
21
22 #include "DYLDRendezvous.h"
23
24 using namespace lldb;
25 using namespace lldb_private;
26
27 /// Locates the address of the rendezvous structure.  Returns the address on
28 /// success and LLDB_INVALID_ADDRESS on failure.
29 static addr_t ResolveRendezvousAddress(Process *process) {
30   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
31   addr_t info_location;
32   addr_t info_addr;
33   Status error;
34
35   if (!process) {
36     if (log)
37       log->Printf("%s null process provided", __FUNCTION__);
38     return LLDB_INVALID_ADDRESS;
39   }
40
41   // Try to get it from our process.  This might be a remote process and might
42   // grab it via some remote-specific mechanism.
43   info_location = process->GetImageInfoAddress();
44   if (log)
45     log->Printf("%s info_location = 0x%" PRIx64, __FUNCTION__, info_location);
46
47   // If the process fails to return an address, fall back to seeing if the
48   // local object file can help us find it.
49   if (info_location == LLDB_INVALID_ADDRESS) {
50     Target *target = &process->GetTarget();
51     if (target) {
52       ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
53       Address addr = obj_file->GetImageInfoAddress(target);
54
55       if (addr.IsValid()) {
56         info_location = addr.GetLoadAddress(target);
57         if (log)
58           log->Printf(
59               "%s resolved via direct object file approach to 0x%" PRIx64,
60               __FUNCTION__, info_location);
61       } else {
62         if (log)
63           log->Printf("%s FAILED - direct object file approach did not yield a "
64                       "valid address",
65                       __FUNCTION__);
66       }
67     }
68   }
69
70   if (info_location == LLDB_INVALID_ADDRESS) {
71     if (log)
72       log->Printf("%s FAILED - invalid info address", __FUNCTION__);
73     return LLDB_INVALID_ADDRESS;
74   }
75
76   if (log)
77     log->Printf("%s reading pointer (%" PRIu32 " bytes) from 0x%" PRIx64,
78                 __FUNCTION__, process->GetAddressByteSize(), info_location);
79
80   info_addr = process->ReadPointerFromMemory(info_location, error);
81   if (error.Fail()) {
82     if (log)
83       log->Printf("%s FAILED - could not read from the info location: %s",
84                   __FUNCTION__, error.AsCString());
85     return LLDB_INVALID_ADDRESS;
86   }
87
88   if (info_addr == 0) {
89     if (log)
90       log->Printf("%s FAILED - the rendezvous address contained at 0x%" PRIx64
91                   " returned a null value",
92                   __FUNCTION__, info_location);
93     return LLDB_INVALID_ADDRESS;
94   }
95
96   return info_addr;
97 }
98
99 DYLDRendezvous::DYLDRendezvous(Process *process)
100     : m_process(process), m_rendezvous_addr(LLDB_INVALID_ADDRESS), m_current(),
101       m_previous(), m_loaded_modules(), m_soentries(), m_added_soentries(),
102       m_removed_soentries() {
103   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
104
105   m_thread_info.valid = false;
106
107   // Cache a copy of the executable path
108   if (m_process) {
109     Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer();
110     if (exe_mod) {
111       m_exe_file_spec = exe_mod->GetPlatformFileSpec();
112       if (log)
113         log->Printf("DYLDRendezvous::%s exe module executable path set: '%s'",
114                     __FUNCTION__, m_exe_file_spec.GetCString());
115     } else {
116       if (log)
117         log->Printf("DYLDRendezvous::%s cannot cache exe module path: null "
118                     "executable module pointer",
119                     __FUNCTION__);
120     }
121   }
122 }
123
124 bool DYLDRendezvous::Resolve() {
125   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
126
127   const size_t word_size = 4;
128   Rendezvous info;
129   size_t address_size;
130   size_t padding;
131   addr_t info_addr;
132   addr_t cursor;
133
134   address_size = m_process->GetAddressByteSize();
135   padding = address_size - word_size;
136   if (log)
137     log->Printf("DYLDRendezvous::%s address size: %" PRIu64
138                 ", padding %" PRIu64,
139                 __FUNCTION__, uint64_t(address_size), uint64_t(padding));
140
141   if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)
142     cursor = info_addr = ResolveRendezvousAddress(m_process);
143   else
144     cursor = info_addr = m_rendezvous_addr;
145   if (log)
146     log->Printf("DYLDRendezvous::%s cursor = 0x%" PRIx64, __FUNCTION__, cursor);
147
148   if (cursor == LLDB_INVALID_ADDRESS)
149     return false;
150
151   if (!(cursor = ReadWord(cursor, &info.version, word_size)))
152     return false;
153
154   if (!(cursor = ReadPointer(cursor + padding, &info.map_addr)))
155     return false;
156
157   if (!(cursor = ReadPointer(cursor, &info.brk)))
158     return false;
159
160   if (!(cursor = ReadWord(cursor, &info.state, word_size)))
161     return false;
162
163   if (!(cursor = ReadPointer(cursor + padding, &info.ldbase)))
164     return false;
165
166   // The rendezvous was successfully read.  Update our internal state.
167   m_rendezvous_addr = info_addr;
168   m_previous = m_current;
169   m_current = info;
170
171   if (UpdateSOEntries(true))
172     return true;
173
174   return UpdateSOEntries();
175 }
176
177 bool DYLDRendezvous::IsValid() {
178   return m_rendezvous_addr != LLDB_INVALID_ADDRESS;
179 }
180
181 bool DYLDRendezvous::UpdateSOEntries(bool fromRemote) {
182   SOEntry entry;
183   LoadedModuleInfoList module_list;
184
185   // If we can't get the SO info from the remote, return failure.
186   if (fromRemote && m_process->LoadModules(module_list) == 0)
187     return false;
188
189   if (!fromRemote && m_current.map_addr == 0)
190     return false;
191
192   // When the previous and current states are consistent this is the first time
193   // we have been asked to update.  Just take a snapshot of the currently
194   // loaded modules.
195   if (m_previous.state == eConsistent && m_current.state == eConsistent)
196     return fromRemote ? SaveSOEntriesFromRemote(module_list)
197                       : TakeSnapshot(m_soentries);
198
199   // If we are about to add or remove a shared object clear out the current
200   // state and take a snapshot of the currently loaded images.
201   if (m_current.state == eAdd || m_current.state == eDelete) {
202     // Some versions of the android dynamic linker might send two notifications
203     // with state == eAdd back to back. Ignore them until we get an eConsistent
204     // notification.
205     if (!(m_previous.state == eConsistent ||
206           (m_previous.state == eAdd && m_current.state == eDelete)))
207       return false;
208
209     m_soentries.clear();
210     if (fromRemote)
211       return SaveSOEntriesFromRemote(module_list);
212
213     m_added_soentries.clear();
214     m_removed_soentries.clear();
215     return TakeSnapshot(m_soentries);
216   }
217   assert(m_current.state == eConsistent);
218
219   // Otherwise check the previous state to determine what to expect and update
220   // accordingly.
221   if (m_previous.state == eAdd)
222     return fromRemote ? AddSOEntriesFromRemote(module_list) : AddSOEntries();
223   else if (m_previous.state == eDelete)
224     return fromRemote ? RemoveSOEntriesFromRemote(module_list)
225                       : RemoveSOEntries();
226
227   return false;
228 }
229
230 bool DYLDRendezvous::FillSOEntryFromModuleInfo(
231     LoadedModuleInfoList::LoadedModuleInfo const &modInfo, SOEntry &entry) {
232   addr_t link_map_addr;
233   addr_t base_addr;
234   addr_t dyn_addr;
235   std::string name;
236
237   if (!modInfo.get_link_map(link_map_addr) || !modInfo.get_base(base_addr) ||
238       !modInfo.get_dynamic(dyn_addr) || !modInfo.get_name(name))
239     return false;
240
241   entry.link_addr = link_map_addr;
242   entry.base_addr = base_addr;
243   entry.dyn_addr = dyn_addr;
244
245   entry.file_spec.SetFile(name, FileSpec::Style::native);
246
247   UpdateBaseAddrIfNecessary(entry, name);
248
249   // not needed if we're using ModuleInfos
250   entry.next = 0;
251   entry.prev = 0;
252   entry.path_addr = 0;
253
254   return true;
255 }
256
257 bool DYLDRendezvous::SaveSOEntriesFromRemote(
258     LoadedModuleInfoList &module_list) {
259   for (auto const &modInfo : module_list.m_list) {
260     SOEntry entry;
261     if (!FillSOEntryFromModuleInfo(modInfo, entry))
262       return false;
263
264     // Only add shared libraries and not the executable.
265     if (!SOEntryIsMainExecutable(entry))
266       m_soentries.push_back(entry);
267   }
268
269   m_loaded_modules = module_list;
270   return true;
271 }
272
273 bool DYLDRendezvous::AddSOEntriesFromRemote(LoadedModuleInfoList &module_list) {
274   for (auto const &modInfo : module_list.m_list) {
275     bool found = false;
276     for (auto const &existing : m_loaded_modules.m_list) {
277       if (modInfo == existing) {
278         found = true;
279         break;
280       }
281     }
282
283     if (found)
284       continue;
285
286     SOEntry entry;
287     if (!FillSOEntryFromModuleInfo(modInfo, entry))
288       return false;
289
290     // Only add shared libraries and not the executable.
291     if (!SOEntryIsMainExecutable(entry))
292       m_soentries.push_back(entry);
293   }
294
295   m_loaded_modules = module_list;
296   return true;
297 }
298
299 bool DYLDRendezvous::RemoveSOEntriesFromRemote(
300     LoadedModuleInfoList &module_list) {
301   for (auto const &existing : m_loaded_modules.m_list) {
302     bool found = false;
303     for (auto const &modInfo : module_list.m_list) {
304       if (modInfo == existing) {
305         found = true;
306         break;
307       }
308     }
309
310     if (found)
311       continue;
312
313     SOEntry entry;
314     if (!FillSOEntryFromModuleInfo(existing, entry))
315       return false;
316
317     // Only add shared libraries and not the executable.
318     if (!SOEntryIsMainExecutable(entry)) {
319       auto pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
320       if (pos == m_soentries.end())
321         return false;
322
323       m_soentries.erase(pos);
324     }
325   }
326
327   m_loaded_modules = module_list;
328   return true;
329 }
330
331 bool DYLDRendezvous::AddSOEntries() {
332   SOEntry entry;
333   iterator pos;
334
335   assert(m_previous.state == eAdd);
336
337   if (m_current.map_addr == 0)
338     return false;
339
340   for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) {
341     if (!ReadSOEntryFromMemory(cursor, entry))
342       return false;
343
344     // Only add shared libraries and not the executable.
345     if (SOEntryIsMainExecutable(entry))
346       continue;
347
348     pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
349     if (pos == m_soentries.end()) {
350       m_soentries.push_back(entry);
351       m_added_soentries.push_back(entry);
352     }
353   }
354
355   return true;
356 }
357
358 bool DYLDRendezvous::RemoveSOEntries() {
359   SOEntryList entry_list;
360   iterator pos;
361
362   assert(m_previous.state == eDelete);
363
364   if (!TakeSnapshot(entry_list))
365     return false;
366
367   for (iterator I = begin(); I != end(); ++I) {
368     pos = std::find(entry_list.begin(), entry_list.end(), *I);
369     if (pos == entry_list.end())
370       m_removed_soentries.push_back(*I);
371   }
372
373   m_soentries = entry_list;
374   return true;
375 }
376
377 bool DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry) {
378   // On some systes the executable is indicated by an empty path in the entry.
379   // On others it is the full path to the executable.
380
381   auto triple = m_process->GetTarget().GetArchitecture().GetTriple();
382   switch (triple.getOS()) {
383   case llvm::Triple::FreeBSD:
384   case llvm::Triple::NetBSD:
385     return entry.file_spec == m_exe_file_spec;
386   case llvm::Triple::Linux:
387     if (triple.isAndroid())
388       return entry.file_spec == m_exe_file_spec;
389     return !entry.file_spec;
390   default:
391     return false;
392   }
393 }
394
395 bool DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) {
396   SOEntry entry;
397
398   if (m_current.map_addr == 0)
399     return false;
400
401   // Clear previous entries since we are about to obtain an up to date list.
402   entry_list.clear();
403
404   for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) {
405     if (!ReadSOEntryFromMemory(cursor, entry))
406       return false;
407
408     // Only add shared libraries and not the executable.
409     if (SOEntryIsMainExecutable(entry))
410       continue;
411
412     entry_list.push_back(entry);
413   }
414
415   return true;
416 }
417
418 addr_t DYLDRendezvous::ReadWord(addr_t addr, uint64_t *dst, size_t size) {
419   Status error;
420
421   *dst = m_process->ReadUnsignedIntegerFromMemory(addr, size, 0, error);
422   if (error.Fail())
423     return 0;
424
425   return addr + size;
426 }
427
428 addr_t DYLDRendezvous::ReadPointer(addr_t addr, addr_t *dst) {
429   Status error;
430
431   *dst = m_process->ReadPointerFromMemory(addr, error);
432   if (error.Fail())
433     return 0;
434
435   return addr + m_process->GetAddressByteSize();
436 }
437
438 std::string DYLDRendezvous::ReadStringFromMemory(addr_t addr) {
439   std::string str;
440   Status error;
441
442   if (addr == LLDB_INVALID_ADDRESS)
443     return std::string();
444
445   m_process->ReadCStringFromMemory(addr, str, error);
446
447   return str;
448 }
449
450 // Returns true if the load bias reported by the linker is incorrect for the
451 // given entry. This function is used to handle cases where we want to work
452 // around a bug in the system linker.
453 static bool isLoadBiasIncorrect(Target &target, const std::string &file_path) {
454   // On Android L (API 21, 22) the load address of the "/system/bin/linker"
455   // isn't filled in correctly.
456   unsigned os_major = target.GetPlatform()->GetOSVersion().getMajor();
457   return target.GetArchitecture().GetTriple().isAndroid() &&
458          (os_major == 21 || os_major == 22) &&
459          (file_path == "/system/bin/linker" ||
460           file_path == "/system/bin/linker64");
461 }
462
463 void DYLDRendezvous::UpdateBaseAddrIfNecessary(SOEntry &entry,
464                                                std::string const &file_path) {
465   // If the load bias reported by the linker is incorrect then fetch the load
466   // address of the file from the proc file system.
467   if (isLoadBiasIncorrect(m_process->GetTarget(), file_path)) {
468     lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
469     bool is_loaded = false;
470     Status error =
471         m_process->GetFileLoadAddress(entry.file_spec, is_loaded, load_addr);
472     if (error.Success() && is_loaded)
473       entry.base_addr = load_addr;
474   }
475 }
476
477 bool DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) {
478   entry.clear();
479
480   entry.link_addr = addr;
481
482   if (!(addr = ReadPointer(addr, &entry.base_addr)))
483     return false;
484
485   // mips adds an extra load offset field to the link map struct on FreeBSD and
486   // NetBSD (need to validate other OSes).
487   // http://svnweb.freebsd.org/base/head/sys/sys/link_elf.h?revision=217153&view=markup#l57
488   const ArchSpec &arch = m_process->GetTarget().GetArchitecture();
489   if ((arch.GetTriple().getOS() == llvm::Triple::FreeBSD ||
490        arch.GetTriple().getOS() == llvm::Triple::NetBSD) &&
491       arch.IsMIPS()) {
492     addr_t mips_l_offs;
493     if (!(addr = ReadPointer(addr, &mips_l_offs)))
494       return false;
495     if (mips_l_offs != 0 && mips_l_offs != entry.base_addr)
496       return false;
497   }
498
499   if (!(addr = ReadPointer(addr, &entry.path_addr)))
500     return false;
501
502   if (!(addr = ReadPointer(addr, &entry.dyn_addr)))
503     return false;
504
505   if (!(addr = ReadPointer(addr, &entry.next)))
506     return false;
507
508   if (!(addr = ReadPointer(addr, &entry.prev)))
509     return false;
510
511   std::string file_path = ReadStringFromMemory(entry.path_addr);
512   entry.file_spec.SetFile(file_path, FileSpec::Style::native);
513
514   UpdateBaseAddrIfNecessary(entry, file_path);
515
516   return true;
517 }
518
519 bool DYLDRendezvous::FindMetadata(const char *name, PThreadField field,
520                                   uint32_t &value) {
521   Target &target = m_process->GetTarget();
522
523   SymbolContextList list;
524   if (!target.GetImages().FindSymbolsWithNameAndType(ConstString(name),
525                                                      eSymbolTypeAny, list))
526     return false;
527
528   Address address = list[0].symbol->GetAddress();
529   addr_t addr = address.GetLoadAddress(&target);
530   if (addr == LLDB_INVALID_ADDRESS)
531     return false;
532
533   Status error;
534   value = (uint32_t)m_process->ReadUnsignedIntegerFromMemory(
535       addr + field * sizeof(uint32_t), sizeof(uint32_t), 0, error);
536   if (error.Fail())
537     return false;
538
539   if (field == eSize)
540     value /= 8; // convert bits to bytes
541
542   return true;
543 }
544
545 const DYLDRendezvous::ThreadInfo &DYLDRendezvous::GetThreadInfo() {
546   if (!m_thread_info.valid) {
547     bool ok = true;
548
549     ok &= FindMetadata("_thread_db_pthread_dtvp", eOffset,
550                        m_thread_info.dtv_offset);
551     ok &=
552         FindMetadata("_thread_db_dtv_dtv", eSize, m_thread_info.dtv_slot_size);
553     ok &= FindMetadata("_thread_db_link_map_l_tls_modid", eOffset,
554                        m_thread_info.modid_offset);
555     ok &= FindMetadata("_thread_db_dtv_t_pointer_val", eOffset,
556                        m_thread_info.tls_offset);
557
558     if (ok)
559       m_thread_info.valid = true;
560   }
561
562   return m_thread_info;
563 }
564
565 void DYLDRendezvous::DumpToLog(Log *log) const {
566   int state = GetState();
567
568   if (!log)
569     return;
570
571   log->PutCString("DYLDRendezvous:");
572   log->Printf("   Address: %" PRIx64, GetRendezvousAddress());
573   log->Printf("   Version: %" PRIu64, GetVersion());
574   log->Printf("   Link   : %" PRIx64, GetLinkMapAddress());
575   log->Printf("   Break  : %" PRIx64, GetBreakAddress());
576   log->Printf("   LDBase : %" PRIx64, GetLDBase());
577   log->Printf("   State  : %s",
578               (state == eConsistent)
579                   ? "consistent"
580                   : (state == eAdd) ? "add" : (state == eDelete) ? "delete"
581                                                                  : "unknown");
582
583   iterator I = begin();
584   iterator E = end();
585
586   if (I != E)
587     log->PutCString("DYLDRendezvous SOEntries:");
588
589   for (int i = 1; I != E; ++I, ++i) {
590     log->Printf("\n   SOEntry [%d] %s", i, I->file_spec.GetCString());
591     log->Printf("      Base : %" PRIx64, I->base_addr);
592     log->Printf("      Path : %" PRIx64, I->path_addr);
593     log->Printf("      Dyn  : %" PRIx64, I->dyn_addr);
594     log->Printf("      Next : %" PRIx64, I->next);
595     log->Printf("      Prev : %" PRIx64, I->prev);
596   }
597 }