1 //===-- ProcessMachCore.cpp ------------------------------------------*- C++
2 //-*-===//
3 //
4 //                     The LLVM Compiler Infrastructure
5 //
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10 
11 // C Includes
12 #include <errno.h>
13 #include <stdlib.h>
14 
15 // C++ Includes
16 #include "llvm/Support/MathExtras.h"
17 #include "llvm/Support/Threading.h"
18 #include <mutex>
19 
20 // Other libraries and framework includes
21 #include "lldb/Core/DataBuffer.h"
22 #include "lldb/Core/Debugger.h"
23 #include "lldb/Core/Log.h"
24 #include "lldb/Core/Module.h"
25 #include "lldb/Core/ModuleSpec.h"
26 #include "lldb/Core/PluginManager.h"
27 #include "lldb/Core/Section.h"
28 #include "lldb/Core/State.h"
29 #include "lldb/Host/Host.h"
30 #include "lldb/Symbol/ObjectFile.h"
31 #include "lldb/Target/MemoryRegionInfo.h"
32 #include "lldb/Target/Target.h"
33 #include "lldb/Target/Thread.h"
34 
35 // Project includes
36 #include "ProcessMachCore.h"
37 #include "StopInfoMachException.h"
38 #include "ThreadMachCore.h"
39 
40 // Needed for the plug-in names for the dynamic loaders.
41 #include "lldb/Utility/SafeMachO.h"
42 
43 #include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
44 #include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h"
45 #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
46 
47 using namespace lldb;
48 using namespace lldb_private;
49 
50 ConstString ProcessMachCore::GetPluginNameStatic() {
51   static ConstString g_name("mach-o-core");
52   return g_name;
53 }
54 
55 const char *ProcessMachCore::GetPluginDescriptionStatic() {
56   return "Mach-O core file debugging plug-in.";
57 }
58 
59 void ProcessMachCore::Terminate() {
60   PluginManager::UnregisterPlugin(ProcessMachCore::CreateInstance);
61 }
62 
63 lldb::ProcessSP ProcessMachCore::CreateInstance(lldb::TargetSP target_sp,
64                                                 ListenerSP listener_sp,
65                                                 const FileSpec *crash_file) {
66   lldb::ProcessSP process_sp;
67   if (crash_file) {
68     const size_t header_size = sizeof(llvm::MachO::mach_header);
69     lldb::DataBufferSP data_sp(crash_file->ReadFileContents(0, header_size));
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.reset(
78               new ProcessMachCore(target_sp, listener_sp, *crash_file));
79       }
80     }
81   }
82   return process_sp;
83 }
84 
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 && m_core_file.Exists()) {
92     // Don't add the Target's architecture to the ModuleSpec - we may be working
93     // with a core file that doesn't have the correct cpusubtype in the header
94     // but we should still try to use it -
95     // ModuleSpecList::FindMatchingModuleSpec
96     // enforces a strict arch mach.
97     ModuleSpec core_module_spec(m_core_file);
98     Error error(ModuleList::GetSharedModule(core_module_spec, m_core_module_sp,
99                                             NULL, NULL, NULL));
100 
101     if (m_core_module_sp) {
102       ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
103       if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile)
104         return true;
105     }
106   }
107   return false;
108 }
109 
110 //----------------------------------------------------------------------
111 // ProcessMachCore constructor
112 //----------------------------------------------------------------------
113 ProcessMachCore::ProcessMachCore(lldb::TargetSP target_sp,
114                                  ListenerSP listener_sp,
115                                  const FileSpec &core_file)
116     : Process(target_sp, listener_sp), m_core_aranges(), m_core_range_infos(),
117       m_core_module_sp(), m_core_file(core_file),
118       m_dyld_addr(LLDB_INVALID_ADDRESS),
119       m_mach_kernel_addr(LLDB_INVALID_ADDRESS), m_dyld_plugin_name() {}
120 
121 //----------------------------------------------------------------------
122 // Destructor
123 //----------------------------------------------------------------------
124 ProcessMachCore::~ProcessMachCore() {
125   Clear();
126   // We need to call finalize on the process before destroying ourselves
127   // to make sure all of the broadcaster cleanup goes as planned. If we
128   // destruct this class, then Process::~Process() might have problems
129   // trying to fully destroy the broadcaster.
130   Finalize();
131 }
132 
133 //----------------------------------------------------------------------
134 // PluginInterface
135 //----------------------------------------------------------------------
136 ConstString ProcessMachCore::GetPluginName() { return GetPluginNameStatic(); }
137 
138 uint32_t ProcessMachCore::GetPluginVersion() { return 1; }
139 
140 bool ProcessMachCore::GetDynamicLoaderAddress(lldb::addr_t addr) {
141   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER |
142                                                   LIBLLDB_LOG_PROCESS));
143   llvm::MachO::mach_header header;
144   Error error;
145   if (DoReadMemory(addr, &header, sizeof(header), error) != sizeof(header))
146     return false;
147   if (header.magic == llvm::MachO::MH_CIGAM ||
148       header.magic == llvm::MachO::MH_CIGAM_64) {
149     header.magic = llvm::ByteSwap_32(header.magic);
150     header.cputype = llvm::ByteSwap_32(header.cputype);
151     header.cpusubtype = llvm::ByteSwap_32(header.cpusubtype);
152     header.filetype = llvm::ByteSwap_32(header.filetype);
153     header.ncmds = llvm::ByteSwap_32(header.ncmds);
154     header.sizeofcmds = llvm::ByteSwap_32(header.sizeofcmds);
155     header.flags = llvm::ByteSwap_32(header.flags);
156   }
157 
158   // TODO: swap header if needed...
159   // printf("0x%16.16" PRIx64 ": magic = 0x%8.8x, file_type= %u\n", vaddr,
160   // header.magic, header.filetype);
161   if (header.magic == llvm::MachO::MH_MAGIC ||
162       header.magic == llvm::MachO::MH_MAGIC_64) {
163     // Check MH_EXECUTABLE to see if we can find the mach image
164     // that contains the shared library list. The dynamic loader
165     // (dyld) is what contains the list for user applications,
166     // and the mach kernel contains a global that has the list
167     // of kexts to load
168     switch (header.filetype) {
169     case llvm::MachO::MH_DYLINKER:
170       // printf("0x%16.16" PRIx64 ": file_type = MH_DYLINKER\n", vaddr);
171       // Address of dyld "struct mach_header" in the core file
172       if (log)
173         log->Printf("ProcessMachCore::GetDynamicLoaderAddress found a user "
174                     "process dyld binary image at 0x%" PRIx64,
175                     addr);
176       m_dyld_addr = addr;
177       return true;
178 
179     case llvm::MachO::MH_EXECUTE:
180       // printf("0x%16.16" PRIx64 ": file_type = MH_EXECUTE\n", vaddr);
181       // Check MH_EXECUTABLE file types to see if the dynamic link object flag
182       // is NOT set. If it isn't, then we have a mach_kernel.
183       if ((header.flags & llvm::MachO::MH_DYLDLINK) == 0) {
184         if (log)
185           log->Printf("ProcessMachCore::GetDynamicLoaderAddress found a mach "
186                       "kernel binary image at 0x%" PRIx64,
187                       addr);
188         // Address of the mach kernel "struct mach_header" in the core file.
189         m_mach_kernel_addr = addr;
190         return true;
191       }
192       break;
193     }
194   }
195   return false;
196 }
197 
198 //----------------------------------------------------------------------
199 // Process Control
200 //----------------------------------------------------------------------
201 Error ProcessMachCore::DoLoadCore() {
202   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER |
203                                                   LIBLLDB_LOG_PROCESS));
204   Error error;
205   if (!m_core_module_sp) {
206     error.SetErrorString("invalid core module");
207     return error;
208   }
209 
210   ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
211   if (core_objfile == NULL) {
212     error.SetErrorString("invalid core object file");
213     return error;
214   }
215 
216   if (core_objfile->GetNumThreadContexts() == 0) {
217     error.SetErrorString("core file doesn't contain any LC_THREAD load "
218                          "commands, or the LC_THREAD architecture is not "
219                          "supported in this lldb");
220     return error;
221   }
222 
223   SectionList *section_list = core_objfile->GetSectionList();
224   if (section_list == NULL) {
225     error.SetErrorString("core file has no sections");
226     return error;
227   }
228 
229   const uint32_t num_sections = section_list->GetNumSections(0);
230   if (num_sections == 0) {
231     error.SetErrorString("core file has no sections");
232     return error;
233   }
234 
235   SetCanJIT(false);
236 
237   llvm::MachO::mach_header header;
238   DataExtractor data(&header, sizeof(header),
239                      m_core_module_sp->GetArchitecture().GetByteOrder(),
240                      m_core_module_sp->GetArchitecture().GetAddressByteSize());
241 
242   bool ranges_are_sorted = true;
243   addr_t vm_addr = 0;
244   for (uint32_t i = 0; i < num_sections; ++i) {
245     Section *section = section_list->GetSectionAtIndex(i).get();
246     if (section) {
247       lldb::addr_t section_vm_addr = section->GetFileAddress();
248       FileRange file_range(section->GetFileOffset(), section->GetFileSize());
249       VMRangeToFileOffset::Entry range_entry(
250           section_vm_addr, section->GetByteSize(), file_range);
251 
252       if (vm_addr > section_vm_addr)
253         ranges_are_sorted = false;
254       vm_addr = section->GetFileAddress();
255       VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
256       //            printf ("LC_SEGMENT[%u] arange=[0x%16.16" PRIx64 " -
257       //            0x%16.16" PRIx64 "), frange=[0x%8.8x - 0x%8.8x)\n",
258       //                    i,
259       //                    range_entry.GetRangeBase(),
260       //                    range_entry.GetRangeEnd(),
261       //                    range_entry.data.GetRangeBase(),
262       //                    range_entry.data.GetRangeEnd());
263 
264       if (last_entry &&
265           last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
266           last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase()) {
267         last_entry->SetRangeEnd(range_entry.GetRangeEnd());
268         last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd());
269         // puts("combine");
270       } else {
271         m_core_aranges.Append(range_entry);
272       }
273       // Some core files don't fill in the permissions correctly. If that is the
274       // case
275       // assume read + execute so clients don't think the memory is not
276       // readable,
277       // or executable. The memory isn't writable since this plug-in doesn't
278       // implement
279       // DoWriteMemory.
280       uint32_t permissions = section->GetPermissions();
281       if (permissions == 0)
282         permissions = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;
283       m_core_range_infos.Append(VMRangeToPermissions::Entry(
284           section_vm_addr, section->GetByteSize(), permissions));
285     }
286   }
287   if (!ranges_are_sorted) {
288     m_core_aranges.Sort();
289     m_core_range_infos.Sort();
290   }
291 
292   if (m_dyld_addr == LLDB_INVALID_ADDRESS ||
293       m_mach_kernel_addr == LLDB_INVALID_ADDRESS) {
294     // We need to locate the main executable in the memory ranges
295     // we have in the core file.  We need to search for both a user-process dyld
296     // binary
297     // and a kernel binary in memory; we must look at all the pages in the
298     // binary so
299     // we don't miss one or the other.  Step through all memory segments
300     // searching for
301     // a kernel binary and for a user process dyld -- we'll decide which to
302     // prefer
303     // later if both are present.
304 
305     const size_t num_core_aranges = m_core_aranges.GetSize();
306     for (size_t i = 0; i < num_core_aranges; ++i) {
307       const VMRangeToFileOffset::Entry *entry =
308           m_core_aranges.GetEntryAtIndex(i);
309       lldb::addr_t section_vm_addr_start = entry->GetRangeBase();
310       lldb::addr_t section_vm_addr_end = entry->GetRangeEnd();
311       for (lldb::addr_t section_vm_addr = section_vm_addr_start;
312            section_vm_addr < section_vm_addr_end; section_vm_addr += 0x1000) {
313         GetDynamicLoaderAddress(section_vm_addr);
314       }
315     }
316   }
317 
318   if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
319     // In the case of multiple kernel images found in the core file via
320     // exhaustive
321     // search, we may not pick the correct one.  See if the
322     // DynamicLoaderDarwinKernel's
323     // search heuristics might identify the correct one.
324     // Most of the time, I expect the address from SearchForDarwinKernel() will
325     // be the
326     // same as the address we found via exhaustive search.
327 
328     if (GetTarget().GetArchitecture().IsValid() == false &&
329         m_core_module_sp.get()) {
330       GetTarget().SetArchitecture(m_core_module_sp->GetArchitecture());
331     }
332 
333     // SearchForDarwinKernel will end up calling back into this this class in
334     // the GetImageInfoAddress
335     // method which will give it the m_mach_kernel_addr/m_dyld_addr it already
336     // has.  Save that aside
337     // and set m_mach_kernel_addr/m_dyld_addr to an invalid address temporarily
338     // so
339     // DynamicLoaderDarwinKernel does a real search for the kernel using its own
340     // heuristics.
341 
342     addr_t saved_mach_kernel_addr = m_mach_kernel_addr;
343     addr_t saved_user_dyld_addr = m_dyld_addr;
344     m_mach_kernel_addr = LLDB_INVALID_ADDRESS;
345     m_dyld_addr = LLDB_INVALID_ADDRESS;
346 
347     addr_t better_kernel_address =
348         DynamicLoaderDarwinKernel::SearchForDarwinKernel(this);
349 
350     m_mach_kernel_addr = saved_mach_kernel_addr;
351     m_dyld_addr = saved_user_dyld_addr;
352 
353     if (better_kernel_address != LLDB_INVALID_ADDRESS) {
354       if (log)
355         log->Printf("ProcessMachCore::DoLoadCore: Using the kernel address "
356                     "from DynamicLoaderDarwinKernel");
357       m_mach_kernel_addr = better_kernel_address;
358     }
359   }
360 
361   // If we found both a user-process dyld and a kernel binary, we need to decide
362   // which to prefer.
363   if (GetCorefilePreference() == eKernelCorefile) {
364     if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
365       if (log)
366         log->Printf("ProcessMachCore::DoLoadCore: Using kernel corefile image "
367                     "at 0x%" PRIx64,
368                     m_mach_kernel_addr);
369       m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
370     } else if (m_dyld_addr != LLDB_INVALID_ADDRESS) {
371       if (log)
372         log->Printf("ProcessMachCore::DoLoadCore: Using user process dyld "
373                     "image at 0x%" PRIx64,
374                     m_dyld_addr);
375       m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
376     }
377   } else {
378     if (m_dyld_addr != LLDB_INVALID_ADDRESS) {
379       if (log)
380         log->Printf("ProcessMachCore::DoLoadCore: Using user process dyld "
381                     "image at 0x%" PRIx64,
382                     m_dyld_addr);
383       m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
384     } else if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
385       if (log)
386         log->Printf("ProcessMachCore::DoLoadCore: Using kernel corefile image "
387                     "at 0x%" PRIx64,
388                     m_mach_kernel_addr);
389       m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
390     }
391   }
392 
393   if (m_dyld_plugin_name != DynamicLoaderMacOSXDYLD::GetPluginNameStatic()) {
394     // For non-user process core files, the permissions on the core file
395     // segments are usually
396     // meaningless, they may be just "read", because we're dealing with kernel
397     // coredumps or
398     // early startup coredumps and the dumper is grabbing pages of memory
399     // without knowing
400     // what they are.  If they aren't marked as "exeuctable", that can break the
401     // unwinder
402     // which will check a pc value to see if it is in an executable segment and
403     // stop the
404     // backtrace early if it is not ("executable" and "unknown" would both be
405     // fine, but
406     // "not executable" will break the unwinder).
407     size_t core_range_infos_size = m_core_range_infos.GetSize();
408     for (size_t i = 0; i < core_range_infos_size; i++) {
409       VMRangeToPermissions::Entry *ent =
410           m_core_range_infos.GetMutableEntryAtIndex(i);
411       ent->data = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;
412     }
413   }
414 
415   // Even if the architecture is set in the target, we need to override
416   // it to match the core file which is always single arch.
417   ArchSpec arch(m_core_module_sp->GetArchitecture());
418   if (arch.GetCore() == ArchSpec::eCore_x86_32_i486) {
419     arch.SetTriple("i386", GetTarget().GetPlatform().get());
420   }
421   if (arch.IsValid())
422     GetTarget().SetArchitecture(arch);
423 
424   return error;
425 }
426 
427 lldb_private::DynamicLoader *ProcessMachCore::GetDynamicLoader() {
428   if (m_dyld_ap.get() == NULL)
429     m_dyld_ap.reset(DynamicLoader::FindPlugin(
430         this,
431         m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString()));
432   return m_dyld_ap.get();
433 }
434 
435 bool ProcessMachCore::UpdateThreadList(ThreadList &old_thread_list,
436                                        ThreadList &new_thread_list) {
437   if (old_thread_list.GetSize(false) == 0) {
438     // Make up the thread the first time this is called so we can setup our one
439     // and only
440     // core thread state.
441     ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
442 
443     if (core_objfile) {
444       const uint32_t num_threads = core_objfile->GetNumThreadContexts();
445       for (lldb::tid_t tid = 0; tid < num_threads; ++tid) {
446         ThreadSP thread_sp(new ThreadMachCore(*this, tid));
447         new_thread_list.AddThread(thread_sp);
448       }
449     }
450   } else {
451     const uint32_t num_threads = old_thread_list.GetSize(false);
452     for (uint32_t i = 0; i < num_threads; ++i)
453       new_thread_list.AddThread(old_thread_list.GetThreadAtIndex(i, false));
454   }
455   return new_thread_list.GetSize(false) > 0;
456 }
457 
458 void ProcessMachCore::RefreshStateAfterStop() {
459   // Let all threads recover from stopping and do any clean up based
460   // on the previous thread state (if any).
461   m_thread_list.RefreshStateAfterStop();
462   // SetThreadStopInfo (m_last_stop_packet);
463 }
464 
465 Error ProcessMachCore::DoDestroy() { return Error(); }
466 
467 //------------------------------------------------------------------
468 // Process Queries
469 //------------------------------------------------------------------
470 
471 bool ProcessMachCore::IsAlive() { return true; }
472 
473 bool ProcessMachCore::WarnBeforeDetach() const { return false; }
474 
475 //------------------------------------------------------------------
476 // Process Memory
477 //------------------------------------------------------------------
478 size_t ProcessMachCore::ReadMemory(addr_t addr, void *buf, size_t size,
479                                    Error &error) {
480   // Don't allow the caching that lldb_private::Process::ReadMemory does
481   // since in core files we have it all cached our our core file anyway.
482   return DoReadMemory(addr, buf, size, error);
483 }
484 
485 size_t ProcessMachCore::DoReadMemory(addr_t addr, void *buf, size_t size,
486                                      Error &error) {
487   ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
488   size_t bytes_read = 0;
489 
490   if (core_objfile) {
491     //----------------------------------------------------------------------
492     // Segments are not always contiguous in mach-o core files. We have core
493     // files that have segments like:
494     //            Address    Size       File off   File size
495     //            ---------- ---------- ---------- ----------
496     // LC_SEGMENT 0x000f6000 0x00001000 0x1d509ee8 0x00001000 --- ---   0
497     // 0x00000000 __TEXT
498     // LC_SEGMENT 0x0f600000 0x00100000 0x1d50aee8 0x00100000 --- ---   0
499     // 0x00000000 __TEXT
500     // LC_SEGMENT 0x000f7000 0x00001000 0x1d60aee8 0x00001000 --- ---   0
501     // 0x00000000 __TEXT
502     //
503     // Any if the user executes the following command:
504     //
505     // (lldb) mem read 0xf6ff0
506     //
507     // We would attempt to read 32 bytes from 0xf6ff0 but would only
508     // get 16 unless we loop through consecutive memory ranges that are
509     // contiguous in the address space, but not in the file data.
510     //----------------------------------------------------------------------
511     while (bytes_read < size) {
512       const addr_t curr_addr = addr + bytes_read;
513       const VMRangeToFileOffset::Entry *core_memory_entry =
514           m_core_aranges.FindEntryThatContains(curr_addr);
515 
516       if (core_memory_entry) {
517         const addr_t offset = curr_addr - core_memory_entry->GetRangeBase();
518         const addr_t bytes_left = core_memory_entry->GetRangeEnd() - curr_addr;
519         const size_t bytes_to_read =
520             std::min(size - bytes_read, (size_t)bytes_left);
521         const size_t curr_bytes_read = core_objfile->CopyData(
522             core_memory_entry->data.GetRangeBase() + offset, bytes_to_read,
523             (char *)buf + bytes_read);
524         if (curr_bytes_read == 0)
525           break;
526         bytes_read += curr_bytes_read;
527       } else {
528         // Only set the error if we didn't read any bytes
529         if (bytes_read == 0)
530           error.SetErrorStringWithFormat(
531               "core file does not contain 0x%" PRIx64, curr_addr);
532         break;
533       }
534     }
535   }
536 
537   return bytes_read;
538 }
539 
540 Error ProcessMachCore::GetMemoryRegionInfo(addr_t load_addr,
541                                            MemoryRegionInfo &region_info) {
542   region_info.Clear();
543   const VMRangeToPermissions::Entry *permission_entry =
544       m_core_range_infos.FindEntryThatContainsOrFollows(load_addr);
545   if (permission_entry) {
546     if (permission_entry->Contains(load_addr)) {
547       region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase());
548       region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd());
549       const Flags permissions(permission_entry->data);
550       region_info.SetReadable(permissions.Test(ePermissionsReadable)
551                                   ? MemoryRegionInfo::eYes
552                                   : MemoryRegionInfo::eNo);
553       region_info.SetWritable(permissions.Test(ePermissionsWritable)
554                                   ? MemoryRegionInfo::eYes
555                                   : MemoryRegionInfo::eNo);
556       region_info.SetExecutable(permissions.Test(ePermissionsExecutable)
557                                     ? MemoryRegionInfo::eYes
558                                     : MemoryRegionInfo::eNo);
559       region_info.SetMapped(MemoryRegionInfo::eYes);
560     } else if (load_addr < permission_entry->GetRangeBase()) {
561       region_info.GetRange().SetRangeBase(load_addr);
562       region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase());
563       region_info.SetReadable(MemoryRegionInfo::eNo);
564       region_info.SetWritable(MemoryRegionInfo::eNo);
565       region_info.SetExecutable(MemoryRegionInfo::eNo);
566       region_info.SetMapped(MemoryRegionInfo::eNo);
567     }
568     return Error();
569   }
570 
571   region_info.GetRange().SetRangeBase(load_addr);
572   region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
573   region_info.SetReadable(MemoryRegionInfo::eNo);
574   region_info.SetWritable(MemoryRegionInfo::eNo);
575   region_info.SetExecutable(MemoryRegionInfo::eNo);
576   region_info.SetMapped(MemoryRegionInfo::eNo);
577   return Error();
578 }
579 
580 void ProcessMachCore::Clear() { m_thread_list.Clear(); }
581 
582 void ProcessMachCore::Initialize() {
583   static llvm::once_flag g_once_flag;
584 
585   llvm::call_once(g_once_flag, []() {
586     PluginManager::RegisterPlugin(GetPluginNameStatic(),
587                                   GetPluginDescriptionStatic(), CreateInstance);
588   });
589 }
590 
591 addr_t ProcessMachCore::GetImageInfoAddress() {
592   // If we found both a user-process dyld and a kernel binary, we need to decide
593   // which to prefer.
594   if (GetCorefilePreference() == eKernelCorefile) {
595     if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
596       return m_mach_kernel_addr;
597     }
598     return m_dyld_addr;
599   } else {
600     if (m_dyld_addr != LLDB_INVALID_ADDRESS) {
601       return m_dyld_addr;
602     }
603     return m_mach_kernel_addr;
604   }
605 }
606 
607 lldb_private::ObjectFile *ProcessMachCore::GetCoreObjectFile() {
608   return m_core_module_sp->GetObjectFile();
609 }
610