xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1 //===-- ProcessMachCore.cpp -----------------------------------------------===//
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 <cerrno>
10 #include <cstdlib>
11 
12 #include "llvm/Support/MathExtras.h"
13 #include "llvm/Support/Threading.h"
14 
15 #include "lldb/Core/Debugger.h"
16 #include "lldb/Core/Module.h"
17 #include "lldb/Core/ModuleSpec.h"
18 #include "lldb/Core/PluginManager.h"
19 #include "lldb/Core/Section.h"
20 #include "lldb/Host/Host.h"
21 #include "lldb/Symbol/LocateSymbolFile.h"
22 #include "lldb/Symbol/ObjectFile.h"
23 #include "lldb/Target/MemoryRegionInfo.h"
24 #include "lldb/Target/SectionLoadList.h"
25 #include "lldb/Target/Target.h"
26 #include "lldb/Target/Thread.h"
27 #include "lldb/Utility/DataBuffer.h"
28 #include "lldb/Utility/LLDBLog.h"
29 #include "lldb/Utility/Log.h"
30 #include "lldb/Utility/State.h"
31 
32 #include "ProcessMachCore.h"
33 #include "Plugins/Process/Utility/StopInfoMachException.h"
34 #include "ThreadMachCore.h"
35 
36 // Needed for the plug-in names for the dynamic loaders.
37 #include "lldb/Host/SafeMachO.h"
38 
39 #include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
40 #include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h"
41 #include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"
42 #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
43 #include "Plugins/Platform/MacOSX/PlatformDarwinKernel.h"
44 
45 #include <memory>
46 #include <mutex>
47 
48 using namespace lldb;
49 using namespace lldb_private;
50 
LLDB_PLUGIN_DEFINE(ProcessMachCore)51 LLDB_PLUGIN_DEFINE(ProcessMachCore)
52 
53 llvm::StringRef ProcessMachCore::GetPluginDescriptionStatic() {
54   return "Mach-O core file debugging plug-in.";
55 }
56 
Terminate()57 void ProcessMachCore::Terminate() {
58   PluginManager::UnregisterPlugin(ProcessMachCore::CreateInstance);
59 }
60 
CreateInstance(lldb::TargetSP target_sp,ListenerSP listener_sp,const FileSpec * crash_file,bool can_connect)61 lldb::ProcessSP ProcessMachCore::CreateInstance(lldb::TargetSP target_sp,
62                                                 ListenerSP listener_sp,
63                                                 const FileSpec *crash_file,
64                                                 bool can_connect) {
65   lldb::ProcessSP process_sp;
66   if (crash_file && !can_connect) {
67     const size_t header_size = sizeof(llvm::MachO::mach_header);
68     auto data_sp = FileSystem::Instance().CreateDataBuffer(
69         crash_file->GetPath(), header_size, 0);
70     if (data_sp && data_sp->GetByteSize() == header_size) {
71       DataExtractor data(data_sp, lldb::eByteOrderLittle, 4);
72 
73       lldb::offset_t data_offset = 0;
74       llvm::MachO::mach_header mach_header;
75       if (ObjectFileMachO::ParseHeader(data, &data_offset, mach_header)) {
76         if (mach_header.filetype == llvm::MachO::MH_CORE)
77           process_sp = std::make_shared<ProcessMachCore>(target_sp, listener_sp,
78                                                          *crash_file);
79       }
80     }
81   }
82   return process_sp;
83 }
84 
CanDebug(lldb::TargetSP target_sp,bool plugin_specified_by_name)85 bool ProcessMachCore::CanDebug(lldb::TargetSP target_sp,
86                                bool plugin_specified_by_name) {
87   if (plugin_specified_by_name)
88     return true;
89 
90   // For now we are just making sure the file exists for a given module
91   if (!m_core_module_sp && FileSystem::Instance().Exists(m_core_file)) {
92     // Don't add the Target's architecture to the ModuleSpec - we may be
93     // working with a core file that doesn't have the correct cpusubtype in the
94     // header but we should still try to use it -
95     // ModuleSpecList::FindMatchingModuleSpec enforces a strict arch mach.
96     ModuleSpec core_module_spec(m_core_file);
97     Status error(ModuleList::GetSharedModule(core_module_spec, m_core_module_sp,
98                                              nullptr, nullptr, nullptr));
99 
100     if (m_core_module_sp) {
101       ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
102       if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile)
103         return true;
104     }
105   }
106   return false;
107 }
108 
109 // ProcessMachCore constructor
ProcessMachCore(lldb::TargetSP target_sp,ListenerSP listener_sp,const FileSpec & core_file)110 ProcessMachCore::ProcessMachCore(lldb::TargetSP target_sp,
111                                  ListenerSP listener_sp,
112                                  const FileSpec &core_file)
113     : PostMortemProcess(target_sp, listener_sp), m_core_aranges(),
114       m_core_range_infos(), m_core_module_sp(), m_core_file(core_file),
115       m_dyld_addr(LLDB_INVALID_ADDRESS),
116       m_mach_kernel_addr(LLDB_INVALID_ADDRESS) {}
117 
118 // Destructor
~ProcessMachCore()119 ProcessMachCore::~ProcessMachCore() {
120   Clear();
121   // We need to call finalize on the process before destroying ourselves to
122   // make sure all of the broadcaster cleanup goes as planned. If we destruct
123   // this class, then Process::~Process() might have problems trying to fully
124   // destroy the broadcaster.
125   Finalize();
126 }
127 
CheckAddressForDyldOrKernel(lldb::addr_t addr,addr_t & dyld,addr_t & kernel)128 bool ProcessMachCore::CheckAddressForDyldOrKernel(lldb::addr_t addr,
129                                                   addr_t &dyld,
130                                                   addr_t &kernel) {
131   Log *log(GetLog(LLDBLog::DynamicLoader | LLDBLog::Process));
132   llvm::MachO::mach_header header;
133   Status error;
134   dyld = kernel = LLDB_INVALID_ADDRESS;
135   if (DoReadMemory(addr, &header, sizeof(header), error) != sizeof(header))
136     return false;
137   if (header.magic == llvm::MachO::MH_CIGAM ||
138       header.magic == llvm::MachO::MH_CIGAM_64) {
139     header.magic = llvm::ByteSwap_32(header.magic);
140     header.cputype = llvm::ByteSwap_32(header.cputype);
141     header.cpusubtype = llvm::ByteSwap_32(header.cpusubtype);
142     header.filetype = llvm::ByteSwap_32(header.filetype);
143     header.ncmds = llvm::ByteSwap_32(header.ncmds);
144     header.sizeofcmds = llvm::ByteSwap_32(header.sizeofcmds);
145     header.flags = llvm::ByteSwap_32(header.flags);
146   }
147 
148   if (header.magic == llvm::MachO::MH_MAGIC ||
149       header.magic == llvm::MachO::MH_MAGIC_64) {
150     // Check MH_EXECUTABLE to see if we can find the mach image that contains
151     // the shared library list. The dynamic loader (dyld) is what contains the
152     // list for user applications, and the mach kernel contains a global that
153     // has the list of kexts to load
154     switch (header.filetype) {
155     case llvm::MachO::MH_DYLINKER:
156       LLDB_LOGF(log,
157                 "ProcessMachCore::%s found a user "
158                 "process dyld binary image at 0x%" PRIx64,
159                 __FUNCTION__, addr);
160       dyld = addr;
161       return true;
162 
163     case llvm::MachO::MH_EXECUTE:
164       // Check MH_EXECUTABLE file types to see if the dynamic link object flag
165       // is NOT set. If it isn't, then we have a mach_kernel.
166       if ((header.flags & llvm::MachO::MH_DYLDLINK) == 0) {
167         LLDB_LOGF(log,
168                   "ProcessMachCore::%s found a mach "
169                   "kernel binary image at 0x%" PRIx64,
170                   __FUNCTION__, addr);
171         // Address of the mach kernel "struct mach_header" in the core file.
172         kernel = addr;
173         return true;
174       }
175       break;
176     }
177   }
178   return false;
179 }
180 
CreateMemoryRegions()181 void ProcessMachCore::CreateMemoryRegions() {
182   ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
183   SectionList *section_list = core_objfile->GetSectionList();
184   const uint32_t num_sections = section_list->GetNumSections(0);
185 
186   bool ranges_are_sorted = true;
187   addr_t vm_addr = 0;
188   for (uint32_t i = 0; i < num_sections; ++i) {
189     Section *section = section_list->GetSectionAtIndex(i).get();
190     if (section && section->GetFileSize() > 0) {
191       lldb::addr_t section_vm_addr = section->GetFileAddress();
192       FileRange file_range(section->GetFileOffset(), section->GetFileSize());
193       VMRangeToFileOffset::Entry range_entry(
194           section_vm_addr, section->GetByteSize(), file_range);
195 
196       if (vm_addr > section_vm_addr)
197         ranges_are_sorted = false;
198       vm_addr = section->GetFileAddress();
199       VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
200 
201       if (last_entry &&
202           last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
203           last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase()) {
204         last_entry->SetRangeEnd(range_entry.GetRangeEnd());
205         last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd());
206       } else {
207         m_core_aranges.Append(range_entry);
208       }
209       // Some core files don't fill in the permissions correctly. If that is
210       // the case assume read + execute so clients don't think the memory is
211       // not readable, or executable. The memory isn't writable since this
212       // plug-in doesn't implement DoWriteMemory.
213       uint32_t permissions = section->GetPermissions();
214       if (permissions == 0)
215         permissions = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;
216       m_core_range_infos.Append(VMRangeToPermissions::Entry(
217           section_vm_addr, section->GetByteSize(), permissions));
218     }
219   }
220   if (!ranges_are_sorted) {
221     m_core_aranges.Sort();
222     m_core_range_infos.Sort();
223   }
224 }
225 
LoadBinariesViaMetadata()226 void ProcessMachCore::LoadBinariesViaMetadata() {
227   Log *log(GetLog(LLDBLog::DynamicLoader | LLDBLog::Process));
228   ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
229   bool found_main_binary_definitively = false;
230 
231   addr_t objfile_binary_value;
232   bool objfile_binary_value_is_offset;
233   UUID objfile_binary_uuid;
234   ObjectFile::BinaryType type;
235 
236   if (core_objfile->GetCorefileMainBinaryInfo(objfile_binary_value,
237                                               objfile_binary_value_is_offset,
238                                               objfile_binary_uuid, type)) {
239     if (log) {
240       log->Printf("ProcessMachCore::LoadBinariesViaMetadata: using binary hint "
241                   "from 'main bin spec' "
242                   "LC_NOTE with UUID %s value 0x%" PRIx64
243                   " value is offset %d and type %d",
244                   objfile_binary_uuid.GetAsString().c_str(),
245                   objfile_binary_value, objfile_binary_value_is_offset, type);
246     }
247 
248     // If this is the xnu kernel, don't load it now.  Note the correct
249     // DynamicLoader plugin to use, and the address of the kernel, and
250     // let the DynamicLoader handle the finding & loading of the binary.
251     if (type == ObjectFile::eBinaryTypeKernel) {
252       m_mach_kernel_addr = objfile_binary_value;
253       m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
254       found_main_binary_definitively = true;
255     } else {
256       const bool force_symbol_search = true;
257       const bool notify = true;
258       if (DynamicLoader::LoadBinaryWithUUIDAndAddress(
259               this, llvm::StringRef(), objfile_binary_uuid,
260               objfile_binary_value, objfile_binary_value_is_offset,
261               force_symbol_search, notify)) {
262         found_main_binary_definitively = true;
263         m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic();
264       }
265       if (type == ObjectFile::eBinaryTypeUser) {
266         m_dyld_addr = objfile_binary_value;
267         m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
268       }
269     }
270   }
271 
272   // This checks for the presence of an LC_IDENT string in a core file;
273   // LC_IDENT is very obsolete and should not be used in new code, but if the
274   // load command is present, let's use the contents.
275   UUID ident_uuid;
276   addr_t ident_binary_addr = LLDB_INVALID_ADDRESS;
277   if (!found_main_binary_definitively) {
278     std::string corefile_identifier = core_objfile->GetIdentifierString();
279 
280     // Search for UUID= and stext= strings in the identifier str.
281     if (corefile_identifier.find("UUID=") != std::string::npos) {
282       size_t p = corefile_identifier.find("UUID=") + strlen("UUID=");
283       std::string uuid_str = corefile_identifier.substr(p, 36);
284       ident_uuid.SetFromStringRef(uuid_str);
285       if (log)
286         log->Printf("Got a UUID from LC_IDENT/kern ver str LC_NOTE: %s",
287                     ident_uuid.GetAsString().c_str());
288     }
289     if (corefile_identifier.find("stext=") != std::string::npos) {
290       size_t p = corefile_identifier.find("stext=") + strlen("stext=");
291       if (corefile_identifier[p] == '0' && corefile_identifier[p + 1] == 'x') {
292         ident_binary_addr =
293             ::strtoul(corefile_identifier.c_str() + p, nullptr, 16);
294         if (log)
295           log->Printf("Got a load address from LC_IDENT/kern ver str "
296                       "LC_NOTE: 0x%" PRIx64,
297                       ident_binary_addr);
298       }
299     }
300 
301     // Search for a "Darwin Kernel" str indicating kernel; else treat as
302     // standalone
303     if (corefile_identifier.find("Darwin Kernel") != std::string::npos &&
304         ident_uuid.IsValid() && ident_binary_addr != LLDB_INVALID_ADDRESS) {
305       if (log)
306         log->Printf(
307             "ProcessMachCore::LoadBinariesViaMetadata: Found kernel binary via "
308             "LC_IDENT/kern ver str LC_NOTE");
309       m_mach_kernel_addr = ident_binary_addr;
310       found_main_binary_definitively = true;
311     } else if (ident_uuid.IsValid()) {
312       // We have no address specified, only a UUID.  Load it at the file
313       // address.
314       const bool value_is_offset = false;
315       const bool force_symbol_search = true;
316       const bool notify = true;
317       if (DynamicLoader::LoadBinaryWithUUIDAndAddress(
318               this, llvm::StringRef(), ident_uuid, ident_binary_addr,
319               value_is_offset, force_symbol_search, notify)) {
320         found_main_binary_definitively = true;
321         m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic();
322       }
323     }
324   }
325 
326   // Finally, load any binaries noted by "load binary" LC_NOTEs in the
327   // corefile
328   core_objfile->LoadCoreFileImages(*this);
329 
330   // LoadCoreFileImges may have set the dynamic loader, e.g. in
331   // PlatformDarwinKernel::LoadPlatformBinaryAndSetup().
332   // If we now have a dynamic loader, save its name so we don't
333   // un-set it later.
334   if (m_dyld_up)
335     m_dyld_plugin_name = GetDynamicLoader()->GetPluginName();
336 }
337 
LoadBinariesViaExhaustiveSearch()338 void ProcessMachCore::LoadBinariesViaExhaustiveSearch() {
339   Log *log(GetLog(LLDBLog::DynamicLoader | LLDBLog::Process));
340 
341   // Search the pages of the corefile for dyld or mach kernel
342   // binaries.  There may be multiple things that look like a kernel
343   // in the corefile; disambiguating to the correct one can be difficult.
344 
345   std::vector<addr_t> dylds_found;
346   std::vector<addr_t> kernels_found;
347 
348   const size_t num_core_aranges = m_core_aranges.GetSize();
349   for (size_t i = 0; i < num_core_aranges; ++i) {
350     const VMRangeToFileOffset::Entry *entry = m_core_aranges.GetEntryAtIndex(i);
351     lldb::addr_t section_vm_addr_start = entry->GetRangeBase();
352     lldb::addr_t section_vm_addr_end = entry->GetRangeEnd();
353     for (lldb::addr_t section_vm_addr = section_vm_addr_start;
354          section_vm_addr < section_vm_addr_end; section_vm_addr += 0x1000) {
355       addr_t dyld, kernel;
356       if (CheckAddressForDyldOrKernel(section_vm_addr, dyld, kernel)) {
357         if (dyld != LLDB_INVALID_ADDRESS)
358           dylds_found.push_back(dyld);
359         if (kernel != LLDB_INVALID_ADDRESS)
360           kernels_found.push_back(kernel);
361       }
362     }
363   }
364 
365   // If we found more than one dyld mach-o header in the corefile,
366   // pick the first one.
367   if (dylds_found.size() > 0)
368     m_dyld_addr = dylds_found[0];
369   if (kernels_found.size() > 0)
370     m_mach_kernel_addr = kernels_found[0];
371 
372   // Zero or one kernels found, we're done.
373   if (kernels_found.size() < 2)
374     return;
375 
376   // In the case of multiple kernel images found in the core file via
377   // exhaustive search, we may not pick the correct one.  See if the
378   // DynamicLoaderDarwinKernel's search heuristics might identify the correct
379   // one.
380 
381   // SearchForDarwinKernel will call this class' GetImageInfoAddress method
382   // which will give it the addresses we already have.
383   // Save those aside and set
384   // m_mach_kernel_addr/m_dyld_addr to an invalid address temporarily so
385   // DynamicLoaderDarwinKernel does a real search for the kernel using its
386   // own heuristics.
387 
388   addr_t saved_mach_kernel_addr = m_mach_kernel_addr;
389   addr_t saved_user_dyld_addr = m_dyld_addr;
390   m_mach_kernel_addr = LLDB_INVALID_ADDRESS;
391   m_dyld_addr = LLDB_INVALID_ADDRESS;
392 
393   addr_t better_kernel_address =
394       DynamicLoaderDarwinKernel::SearchForDarwinKernel(this);
395 
396   m_mach_kernel_addr = saved_mach_kernel_addr;
397   m_dyld_addr = saved_user_dyld_addr;
398 
399   if (better_kernel_address != LLDB_INVALID_ADDRESS) {
400     LLDB_LOGF(log,
401               "ProcessMachCore::%s: Using "
402               "the kernel address "
403               "from DynamicLoaderDarwinKernel",
404               __FUNCTION__);
405     m_mach_kernel_addr = better_kernel_address;
406   }
407 }
408 
LoadBinariesAndSetDYLD()409 void ProcessMachCore::LoadBinariesAndSetDYLD() {
410   Log *log(GetLog(LLDBLog::DynamicLoader | LLDBLog::Process));
411 
412   LoadBinariesViaMetadata();
413   if (m_dyld_plugin_name.empty())
414     LoadBinariesViaExhaustiveSearch();
415 
416   if (m_dyld_plugin_name.empty()) {
417     // If we found both a user-process dyld and a kernel binary, we need to
418     // decide which to prefer.
419     if (GetCorefilePreference() == eKernelCorefile) {
420       if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
421         LLDB_LOGF(log,
422                   "ProcessMachCore::%s: Using kernel "
423                   "corefile image "
424                   "at 0x%" PRIx64,
425                   __FUNCTION__, m_mach_kernel_addr);
426         m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
427       } else if (m_dyld_addr != LLDB_INVALID_ADDRESS) {
428         LLDB_LOGF(log,
429                   "ProcessMachCore::%s: Using user process dyld "
430                   "image at 0x%" PRIx64,
431                   __FUNCTION__, m_dyld_addr);
432         m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
433       }
434     } else {
435       if (m_dyld_addr != LLDB_INVALID_ADDRESS) {
436         LLDB_LOGF(log,
437                   "ProcessMachCore::%s: Using user process dyld "
438                   "image at 0x%" PRIx64,
439                   __FUNCTION__, m_dyld_addr);
440         m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
441       } else if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
442         LLDB_LOGF(log,
443                   "ProcessMachCore::%s: Using kernel "
444                   "corefile image "
445                   "at 0x%" PRIx64,
446                   __FUNCTION__, m_mach_kernel_addr);
447         m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
448       }
449     }
450   }
451 }
452 
CleanupMemoryRegionPermissions()453 void ProcessMachCore::CleanupMemoryRegionPermissions() {
454   if (m_dyld_plugin_name != DynamicLoaderMacOSXDYLD::GetPluginNameStatic()) {
455     // For non-user process core files, the permissions on the core file
456     // segments are usually meaningless, they may be just "read", because we're
457     // dealing with kernel coredumps or early startup coredumps and the dumper
458     // is grabbing pages of memory without knowing what they are.  If they
459     // aren't marked as "executable", that can break the unwinder which will
460     // check a pc value to see if it is in an executable segment and stop the
461     // backtrace early if it is not ("executable" and "unknown" would both be
462     // fine, but "not executable" will break the unwinder).
463     size_t core_range_infos_size = m_core_range_infos.GetSize();
464     for (size_t i = 0; i < core_range_infos_size; i++) {
465       VMRangeToPermissions::Entry *ent =
466           m_core_range_infos.GetMutableEntryAtIndex(i);
467       ent->data = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;
468     }
469   }
470 }
471 
472 // Process Control
DoLoadCore()473 Status ProcessMachCore::DoLoadCore() {
474   Status error;
475   if (!m_core_module_sp) {
476     error.SetErrorString("invalid core module");
477     return error;
478   }
479 
480   ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
481   if (core_objfile == nullptr) {
482     error.SetErrorString("invalid core object file");
483     return error;
484   }
485 
486   if (core_objfile->GetNumThreadContexts() == 0) {
487     error.SetErrorString("core file doesn't contain any LC_THREAD load "
488                          "commands, or the LC_THREAD architecture is not "
489                          "supported in this lldb");
490     return error;
491   }
492 
493   SetCanJIT(false);
494 
495   // The corefile's architecture is our best starting point.
496   ArchSpec arch(m_core_module_sp->GetArchitecture());
497   if (arch.IsValid())
498     GetTarget().SetArchitecture(arch);
499 
500   CreateMemoryRegions();
501 
502   LoadBinariesAndSetDYLD();
503 
504   CleanupMemoryRegionPermissions();
505 
506   addr_t address_mask = core_objfile->GetAddressMask();
507   if (address_mask != 0) {
508     SetCodeAddressMask(address_mask);
509     SetDataAddressMask(address_mask);
510   }
511   return error;
512 }
513 
GetDynamicLoader()514 lldb_private::DynamicLoader *ProcessMachCore::GetDynamicLoader() {
515   if (m_dyld_up.get() == nullptr)
516     m_dyld_up.reset(DynamicLoader::FindPlugin(this, m_dyld_plugin_name));
517   return m_dyld_up.get();
518 }
519 
DoUpdateThreadList(ThreadList & old_thread_list,ThreadList & new_thread_list)520 bool ProcessMachCore::DoUpdateThreadList(ThreadList &old_thread_list,
521                                          ThreadList &new_thread_list) {
522   if (old_thread_list.GetSize(false) == 0) {
523     // Make up the thread the first time this is called so we can setup our one
524     // and only core thread state.
525     ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
526 
527     if (core_objfile) {
528       const uint32_t num_threads = core_objfile->GetNumThreadContexts();
529       for (lldb::tid_t tid = 0; tid < num_threads; ++tid) {
530         ThreadSP thread_sp(new ThreadMachCore(*this, tid));
531         new_thread_list.AddThread(thread_sp);
532       }
533     }
534   } else {
535     const uint32_t num_threads = old_thread_list.GetSize(false);
536     for (uint32_t i = 0; i < num_threads; ++i)
537       new_thread_list.AddThread(old_thread_list.GetThreadAtIndex(i, false));
538   }
539   return new_thread_list.GetSize(false) > 0;
540 }
541 
RefreshStateAfterStop()542 void ProcessMachCore::RefreshStateAfterStop() {
543   // Let all threads recover from stopping and do any clean up based on the
544   // previous thread state (if any).
545   m_thread_list.RefreshStateAfterStop();
546   // SetThreadStopInfo (m_last_stop_packet);
547 }
548 
DoDestroy()549 Status ProcessMachCore::DoDestroy() { return Status(); }
550 
551 // Process Queries
552 
IsAlive()553 bool ProcessMachCore::IsAlive() { return true; }
554 
WarnBeforeDetach() const555 bool ProcessMachCore::WarnBeforeDetach() const { return false; }
556 
557 // Process Memory
ReadMemory(addr_t addr,void * buf,size_t size,Status & error)558 size_t ProcessMachCore::ReadMemory(addr_t addr, void *buf, size_t size,
559                                    Status &error) {
560   // Don't allow the caching that lldb_private::Process::ReadMemory does since
561   // in core files we have it all cached our our core file anyway.
562   return DoReadMemory(addr, buf, size, error);
563 }
564 
DoReadMemory(addr_t addr,void * buf,size_t size,Status & error)565 size_t ProcessMachCore::DoReadMemory(addr_t addr, void *buf, size_t size,
566                                      Status &error) {
567   ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
568   size_t bytes_read = 0;
569 
570   if (core_objfile) {
571     // Segments are not always contiguous in mach-o core files. We have core
572     // files that have segments like:
573     //            Address    Size       File off   File size
574     //            ---------- ---------- ---------- ----------
575     // LC_SEGMENT 0x000f6000 0x00001000 0x1d509ee8 0x00001000 --- ---   0
576     // 0x00000000 __TEXT LC_SEGMENT 0x0f600000 0x00100000 0x1d50aee8 0x00100000
577     // --- ---   0 0x00000000 __TEXT LC_SEGMENT 0x000f7000 0x00001000
578     // 0x1d60aee8 0x00001000 --- ---   0 0x00000000 __TEXT
579     //
580     // Any if the user executes the following command:
581     //
582     // (lldb) mem read 0xf6ff0
583     //
584     // We would attempt to read 32 bytes from 0xf6ff0 but would only get 16
585     // unless we loop through consecutive memory ranges that are contiguous in
586     // the address space, but not in the file data.
587     while (bytes_read < size) {
588       const addr_t curr_addr = addr + bytes_read;
589       const VMRangeToFileOffset::Entry *core_memory_entry =
590           m_core_aranges.FindEntryThatContains(curr_addr);
591 
592       if (core_memory_entry) {
593         const addr_t offset = curr_addr - core_memory_entry->GetRangeBase();
594         const addr_t bytes_left = core_memory_entry->GetRangeEnd() - curr_addr;
595         const size_t bytes_to_read =
596             std::min(size - bytes_read, (size_t)bytes_left);
597         const size_t curr_bytes_read = core_objfile->CopyData(
598             core_memory_entry->data.GetRangeBase() + offset, bytes_to_read,
599             (char *)buf + bytes_read);
600         if (curr_bytes_read == 0)
601           break;
602         bytes_read += curr_bytes_read;
603       } else {
604         // Only set the error if we didn't read any bytes
605         if (bytes_read == 0)
606           error.SetErrorStringWithFormat(
607               "core file does not contain 0x%" PRIx64, curr_addr);
608         break;
609       }
610     }
611   }
612 
613   return bytes_read;
614 }
615 
DoGetMemoryRegionInfo(addr_t load_addr,MemoryRegionInfo & region_info)616 Status ProcessMachCore::DoGetMemoryRegionInfo(addr_t load_addr,
617                                               MemoryRegionInfo &region_info) {
618   region_info.Clear();
619   const VMRangeToPermissions::Entry *permission_entry =
620       m_core_range_infos.FindEntryThatContainsOrFollows(load_addr);
621   if (permission_entry) {
622     if (permission_entry->Contains(load_addr)) {
623       region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase());
624       region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd());
625       const Flags permissions(permission_entry->data);
626       region_info.SetReadable(permissions.Test(ePermissionsReadable)
627                                   ? MemoryRegionInfo::eYes
628                                   : MemoryRegionInfo::eNo);
629       region_info.SetWritable(permissions.Test(ePermissionsWritable)
630                                   ? MemoryRegionInfo::eYes
631                                   : MemoryRegionInfo::eNo);
632       region_info.SetExecutable(permissions.Test(ePermissionsExecutable)
633                                     ? MemoryRegionInfo::eYes
634                                     : MemoryRegionInfo::eNo);
635       region_info.SetMapped(MemoryRegionInfo::eYes);
636     } else if (load_addr < permission_entry->GetRangeBase()) {
637       region_info.GetRange().SetRangeBase(load_addr);
638       region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase());
639       region_info.SetReadable(MemoryRegionInfo::eNo);
640       region_info.SetWritable(MemoryRegionInfo::eNo);
641       region_info.SetExecutable(MemoryRegionInfo::eNo);
642       region_info.SetMapped(MemoryRegionInfo::eNo);
643     }
644     return Status();
645   }
646 
647   region_info.GetRange().SetRangeBase(load_addr);
648   region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
649   region_info.SetReadable(MemoryRegionInfo::eNo);
650   region_info.SetWritable(MemoryRegionInfo::eNo);
651   region_info.SetExecutable(MemoryRegionInfo::eNo);
652   region_info.SetMapped(MemoryRegionInfo::eNo);
653   return Status();
654 }
655 
Clear()656 void ProcessMachCore::Clear() { m_thread_list.Clear(); }
657 
Initialize()658 void ProcessMachCore::Initialize() {
659   static llvm::once_flag g_once_flag;
660 
661   llvm::call_once(g_once_flag, []() {
662     PluginManager::RegisterPlugin(GetPluginNameStatic(),
663                                   GetPluginDescriptionStatic(), CreateInstance);
664   });
665 }
666 
GetImageInfoAddress()667 addr_t ProcessMachCore::GetImageInfoAddress() {
668   // If we found both a user-process dyld and a kernel binary, we need to
669   // decide which to prefer.
670   if (GetCorefilePreference() == eKernelCorefile) {
671     if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
672       return m_mach_kernel_addr;
673     }
674     return m_dyld_addr;
675   } else {
676     if (m_dyld_addr != LLDB_INVALID_ADDRESS) {
677       return m_dyld_addr;
678     }
679     return m_mach_kernel_addr;
680   }
681 }
682 
GetCoreObjectFile()683 lldb_private::ObjectFile *ProcessMachCore::GetCoreObjectFile() {
684   return m_core_module_sp->GetObjectFile();
685 }
686