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/Debugger.h"
22 #include "lldb/Core/Module.h"
23 #include "lldb/Core/ModuleSpec.h"
24 #include "lldb/Core/PluginManager.h"
25 #include "lldb/Core/Section.h"
26 #include "lldb/Host/Host.h"
27 #include "lldb/Symbol/ObjectFile.h"
28 #include "lldb/Target/MemoryRegionInfo.h"
29 #include "lldb/Target/Target.h"
30 #include "lldb/Target/Thread.h"
31 #include "lldb/Utility/DataBuffer.h"
32 #include "lldb/Utility/DataBufferLLVM.h"
33 #include "lldb/Utility/Log.h"
34 #include "lldb/Utility/State.h"
35 
36 // Project includes
37 #include "ProcessMachCore.h"
38 #include "Plugins/Process/Utility/StopInfoMachException.h"
39 #include "ThreadMachCore.h"
40 
41 // Needed for the plug-in names for the dynamic loaders.
42 #include "lldb/Host/SafeMachO.h"
43 
44 #include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
45 #include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h"
46 #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
47 
48 using namespace lldb;
49 using namespace lldb_private;
50 
51 ConstString ProcessMachCore::GetPluginNameStatic() {
52   static ConstString g_name("mach-o-core");
53   return g_name;
54 }
55 
56 const char *ProcessMachCore::GetPluginDescriptionStatic() {
57   return "Mach-O core file debugging plug-in.";
58 }
59 
60 void ProcessMachCore::Terminate() {
61   PluginManager::UnregisterPlugin(ProcessMachCore::CreateInstance);
62 }
63 
64 lldb::ProcessSP ProcessMachCore::CreateInstance(lldb::TargetSP target_sp,
65                                                 ListenerSP listener_sp,
66                                                 const FileSpec *crash_file) {
67   lldb::ProcessSP process_sp;
68   if (crash_file) {
69     const size_t header_size = sizeof(llvm::MachO::mach_header);
70     auto data_sp =
71         DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(), header_size, 0);
72     if (data_sp && data_sp->GetByteSize() == header_size) {
73       DataExtractor data(data_sp, lldb::eByteOrderLittle, 4);
74 
75       lldb::offset_t data_offset = 0;
76       llvm::MachO::mach_header mach_header;
77       if (ObjectFileMachO::ParseHeader(data, &data_offset, mach_header)) {
78         if (mach_header.filetype == llvm::MachO::MH_CORE)
79           process_sp.reset(
80               new ProcessMachCore(target_sp, listener_sp, *crash_file));
81       }
82     }
83   }
84   return process_sp;
85 }
86 
87 bool ProcessMachCore::CanDebug(lldb::TargetSP target_sp,
88                                bool plugin_specified_by_name) {
89   if (plugin_specified_by_name)
90     return true;
91 
92   // For now we are just making sure the file exists for a given module
93   if (!m_core_module_sp && m_core_file.Exists()) {
94     // Don't add the Target's architecture to the ModuleSpec - we may be
95     // working with a core file that doesn't have the correct cpusubtype in the
96     // header but we should still try to use it -
97     // ModuleSpecList::FindMatchingModuleSpec enforces a strict arch mach.
98     ModuleSpec core_module_spec(m_core_file);
99     Status error(ModuleList::GetSharedModule(core_module_spec, m_core_module_sp,
100                                              NULL, NULL, NULL));
101 
102     if (m_core_module_sp) {
103       ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
104       if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile)
105         return true;
106     }
107   }
108   return false;
109 }
110 
111 //----------------------------------------------------------------------
112 // ProcessMachCore constructor
113 //----------------------------------------------------------------------
114 ProcessMachCore::ProcessMachCore(lldb::TargetSP target_sp,
115                                  ListenerSP listener_sp,
116                                  const FileSpec &core_file)
117     : Process(target_sp, listener_sp), m_core_aranges(), m_core_range_infos(),
118       m_core_module_sp(), m_core_file(core_file),
119       m_dyld_addr(LLDB_INVALID_ADDRESS),
120       m_mach_kernel_addr(LLDB_INVALID_ADDRESS), m_dyld_plugin_name() {}
121 
122 //----------------------------------------------------------------------
123 // Destructor
124 //----------------------------------------------------------------------
125 ProcessMachCore::~ProcessMachCore() {
126   Clear();
127   // We need to call finalize on the process before destroying ourselves to
128   // make sure all of the broadcaster cleanup goes as planned. If we destruct
129   // this class, then Process::~Process() might have problems trying to fully
130   // destroy the broadcaster.
131   Finalize();
132 }
133 
134 //----------------------------------------------------------------------
135 // PluginInterface
136 //----------------------------------------------------------------------
137 ConstString ProcessMachCore::GetPluginName() { return GetPluginNameStatic(); }
138 
139 uint32_t ProcessMachCore::GetPluginVersion() { return 1; }
140 
141 bool ProcessMachCore::GetDynamicLoaderAddress(lldb::addr_t addr) {
142   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER |
143                                                   LIBLLDB_LOG_PROCESS));
144   llvm::MachO::mach_header header;
145   Status error;
146   if (DoReadMemory(addr, &header, sizeof(header), error) != sizeof(header))
147     return false;
148   if (header.magic == llvm::MachO::MH_CIGAM ||
149       header.magic == llvm::MachO::MH_CIGAM_64) {
150     header.magic = llvm::ByteSwap_32(header.magic);
151     header.cputype = llvm::ByteSwap_32(header.cputype);
152     header.cpusubtype = llvm::ByteSwap_32(header.cpusubtype);
153     header.filetype = llvm::ByteSwap_32(header.filetype);
154     header.ncmds = llvm::ByteSwap_32(header.ncmds);
155     header.sizeofcmds = llvm::ByteSwap_32(header.sizeofcmds);
156     header.flags = llvm::ByteSwap_32(header.flags);
157   }
158 
159   // TODO: swap header if needed...
160   // printf("0x%16.16" PRIx64 ": magic = 0x%8.8x, file_type= %u\n", vaddr,
161   // header.magic, header.filetype);
162   if (header.magic == llvm::MachO::MH_MAGIC ||
163       header.magic == llvm::MachO::MH_MAGIC_64) {
164     // Check MH_EXECUTABLE to see if we can find the mach image that contains
165     // the shared library list. The dynamic loader (dyld) is what contains the
166     // list for user applications, and the mach kernel contains a global that
167     // has the list 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 Status ProcessMachCore::DoLoadCore() {
202   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER |
203                                                   LIBLLDB_LOG_PROCESS));
204   Status 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
274       // the case assume read + execute so clients don't think the memory is
275       // not readable, or executable. The memory isn't writable since this
276       // plug-in doesn't implement DoWriteMemory.
277       uint32_t permissions = section->GetPermissions();
278       if (permissions == 0)
279         permissions = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;
280       m_core_range_infos.Append(VMRangeToPermissions::Entry(
281           section_vm_addr, section->GetByteSize(), permissions));
282     }
283   }
284   if (!ranges_are_sorted) {
285     m_core_aranges.Sort();
286     m_core_range_infos.Sort();
287   }
288 
289 
290   bool found_main_binary_definitively = false;
291 
292   addr_t objfile_binary_addr;
293   UUID objfile_binary_uuid;
294   if (core_objfile->GetCorefileMainBinaryInfo (objfile_binary_addr, objfile_binary_uuid))
295   {
296     if (objfile_binary_addr != LLDB_INVALID_ADDRESS)
297     {
298         m_mach_kernel_addr = objfile_binary_addr;
299         found_main_binary_definitively = true;
300         if (log)
301             log->Printf ("ProcessMachCore::DoLoadCore: using kernel address 0x%" PRIx64
302                          " from LC_NOTE 'main bin spec' load command.", m_mach_kernel_addr);
303     }
304   }
305 
306   // This checks for the presence of an LC_IDENT string in a core file;
307   // LC_IDENT is very obsolete and should not be used in new code, but if the
308   // load command is present, let's use the contents.
309   std::string corefile_identifier = core_objfile->GetIdentifierString();
310   if (found_main_binary_definitively == false
311       && corefile_identifier.find("Darwin Kernel") != std::string::npos) {
312       UUID uuid;
313       addr_t addr = LLDB_INVALID_ADDRESS;
314       if (corefile_identifier.find("UUID=") != std::string::npos) {
315           size_t p = corefile_identifier.find("UUID=") + strlen("UUID=");
316           std::string uuid_str = corefile_identifier.substr(p, 36);
317           uuid.SetFromStringRef(uuid_str);
318       }
319       if (corefile_identifier.find("stext=") != std::string::npos) {
320           size_t p = corefile_identifier.find("stext=") + strlen("stext=");
321           if (corefile_identifier[p] == '0' && corefile_identifier[p + 1] == 'x') {
322               errno = 0;
323               addr = ::strtoul(corefile_identifier.c_str() + p, NULL, 16);
324               if (errno != 0 || addr == 0)
325                   addr = LLDB_INVALID_ADDRESS;
326           }
327       }
328       if (uuid.IsValid() && addr != LLDB_INVALID_ADDRESS) {
329           m_mach_kernel_addr = addr;
330           found_main_binary_definitively = true;
331           if (log)
332             log->Printf("ProcessMachCore::DoLoadCore: Using the kernel address 0x%" PRIx64
333                         " from LC_IDENT/LC_NOTE 'kern ver str' string: '%s'", addr, corefile_identifier.c_str());
334       }
335   }
336 
337   if (found_main_binary_definitively == false
338       && (m_dyld_addr == LLDB_INVALID_ADDRESS
339           || m_mach_kernel_addr == LLDB_INVALID_ADDRESS)) {
340     // We need to locate the main executable in the memory ranges we have in
341     // the core file.  We need to search for both a user-process dyld binary
342     // and a kernel binary in memory; we must look at all the pages in the
343     // binary so we don't miss one or the other.  Step through all memory
344     // segments searching for a kernel binary and for a user process dyld --
345     // we'll decide which to prefer later if both are present.
346 
347     const size_t num_core_aranges = m_core_aranges.GetSize();
348     for (size_t i = 0; i < num_core_aranges; ++i) {
349       const VMRangeToFileOffset::Entry *entry =
350           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         GetDynamicLoaderAddress(section_vm_addr);
356       }
357     }
358   }
359 
360   if (found_main_binary_definitively == false
361        && m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
362     // In the case of multiple kernel images found in the core file via
363     // exhaustive search, we may not pick the correct one.  See if the
364     // DynamicLoaderDarwinKernel's search heuristics might identify the correct
365     // one. Most of the time, I expect the address from SearchForDarwinKernel()
366     // will be the same as the address we found via exhaustive search.
367 
368     if (GetTarget().GetArchitecture().IsValid() == false &&
369         m_core_module_sp.get()) {
370       GetTarget().SetArchitecture(m_core_module_sp->GetArchitecture());
371     }
372 
373     // SearchForDarwinKernel will end up calling back into this this class in
374     // the GetImageInfoAddress method which will give it the
375     // m_mach_kernel_addr/m_dyld_addr it already has.  Save that aside and set
376     // m_mach_kernel_addr/m_dyld_addr to an invalid address temporarily so
377     // DynamicLoaderDarwinKernel does a real search for the kernel using its
378     // own heuristics.
379 
380     addr_t saved_mach_kernel_addr = m_mach_kernel_addr;
381     addr_t saved_user_dyld_addr = m_dyld_addr;
382     m_mach_kernel_addr = LLDB_INVALID_ADDRESS;
383     m_dyld_addr = LLDB_INVALID_ADDRESS;
384 
385     addr_t better_kernel_address =
386         DynamicLoaderDarwinKernel::SearchForDarwinKernel(this);
387 
388     m_mach_kernel_addr = saved_mach_kernel_addr;
389     m_dyld_addr = saved_user_dyld_addr;
390 
391     if (better_kernel_address != LLDB_INVALID_ADDRESS) {
392       if (log)
393         log->Printf("ProcessMachCore::DoLoadCore: Using the kernel address "
394                     "from DynamicLoaderDarwinKernel");
395       m_mach_kernel_addr = better_kernel_address;
396     }
397   }
398 
399   // If we found both a user-process dyld and a kernel binary, we need to
400   // decide which to prefer.
401   if (GetCorefilePreference() == eKernelCorefile) {
402     if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
403       if (log)
404         log->Printf("ProcessMachCore::DoLoadCore: Using kernel corefile image "
405                     "at 0x%" PRIx64,
406                     m_mach_kernel_addr);
407       m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
408     } else if (m_dyld_addr != LLDB_INVALID_ADDRESS) {
409       if (log)
410         log->Printf("ProcessMachCore::DoLoadCore: Using user process dyld "
411                     "image at 0x%" PRIx64,
412                     m_dyld_addr);
413       m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
414     }
415   } else {
416     if (m_dyld_addr != LLDB_INVALID_ADDRESS) {
417       if (log)
418         log->Printf("ProcessMachCore::DoLoadCore: Using user process dyld "
419                     "image at 0x%" PRIx64,
420                     m_dyld_addr);
421       m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
422     } else if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
423       if (log)
424         log->Printf("ProcessMachCore::DoLoadCore: Using kernel corefile image "
425                     "at 0x%" PRIx64,
426                     m_mach_kernel_addr);
427       m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
428     }
429   }
430 
431   if (m_dyld_plugin_name != DynamicLoaderMacOSXDYLD::GetPluginNameStatic()) {
432     // For non-user process core files, the permissions on the core file
433     // segments are usually meaningless, they may be just "read", because we're
434     // dealing with kernel coredumps or early startup coredumps and the dumper
435     // is grabbing pages of memory without knowing what they are.  If they
436     // aren't marked as "exeuctable", that can break the unwinder which will
437     // check a pc value to see if it is in an executable segment and stop the
438     // backtrace early if it is not ("executable" and "unknown" would both be
439     // fine, but "not executable" will break the unwinder).
440     size_t core_range_infos_size = m_core_range_infos.GetSize();
441     for (size_t i = 0; i < core_range_infos_size; i++) {
442       VMRangeToPermissions::Entry *ent =
443           m_core_range_infos.GetMutableEntryAtIndex(i);
444       ent->data = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;
445     }
446   }
447 
448   // Even if the architecture is set in the target, we need to override it to
449   // match the core file which is always single arch.
450   ArchSpec arch(m_core_module_sp->GetArchitecture());
451   if (arch.GetCore() == ArchSpec::eCore_x86_32_i486) {
452     arch = Platform::GetAugmentedArchSpec(GetTarget().GetPlatform().get(), "i386");
453   }
454   if (arch.IsValid())
455     GetTarget().SetArchitecture(arch);
456 
457   return error;
458 }
459 
460 lldb_private::DynamicLoader *ProcessMachCore::GetDynamicLoader() {
461   if (m_dyld_ap.get() == NULL)
462     m_dyld_ap.reset(DynamicLoader::FindPlugin(
463         this,
464         m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString()));
465   return m_dyld_ap.get();
466 }
467 
468 bool ProcessMachCore::UpdateThreadList(ThreadList &old_thread_list,
469                                        ThreadList &new_thread_list) {
470   if (old_thread_list.GetSize(false) == 0) {
471     // Make up the thread the first time this is called so we can setup our one
472     // and only core thread state.
473     ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
474 
475     if (core_objfile) {
476       const uint32_t num_threads = core_objfile->GetNumThreadContexts();
477       for (lldb::tid_t tid = 0; tid < num_threads; ++tid) {
478         ThreadSP thread_sp(new ThreadMachCore(*this, tid));
479         new_thread_list.AddThread(thread_sp);
480       }
481     }
482   } else {
483     const uint32_t num_threads = old_thread_list.GetSize(false);
484     for (uint32_t i = 0; i < num_threads; ++i)
485       new_thread_list.AddThread(old_thread_list.GetThreadAtIndex(i, false));
486   }
487   return new_thread_list.GetSize(false) > 0;
488 }
489 
490 void ProcessMachCore::RefreshStateAfterStop() {
491   // Let all threads recover from stopping and do any clean up based on the
492   // previous thread state (if any).
493   m_thread_list.RefreshStateAfterStop();
494   // SetThreadStopInfo (m_last_stop_packet);
495 }
496 
497 Status ProcessMachCore::DoDestroy() { return Status(); }
498 
499 //------------------------------------------------------------------
500 // Process Queries
501 //------------------------------------------------------------------
502 
503 bool ProcessMachCore::IsAlive() { return true; }
504 
505 bool ProcessMachCore::WarnBeforeDetach() const { return false; }
506 
507 //------------------------------------------------------------------
508 // Process Memory
509 //------------------------------------------------------------------
510 size_t ProcessMachCore::ReadMemory(addr_t addr, void *buf, size_t size,
511                                    Status &error) {
512   // Don't allow the caching that lldb_private::Process::ReadMemory does since
513   // in core files we have it all cached our our core file anyway.
514   return DoReadMemory(addr, buf, size, error);
515 }
516 
517 size_t ProcessMachCore::DoReadMemory(addr_t addr, void *buf, size_t size,
518                                      Status &error) {
519   ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
520   size_t bytes_read = 0;
521 
522   if (core_objfile) {
523     //----------------------------------------------------------------------
524     // Segments are not always contiguous in mach-o core files. We have core
525     // files that have segments like:
526     //            Address    Size       File off   File size
527     //            ---------- ---------- ---------- ----------
528     // LC_SEGMENT 0x000f6000 0x00001000 0x1d509ee8 0x00001000 --- ---   0
529     // 0x00000000 __TEXT LC_SEGMENT 0x0f600000 0x00100000 0x1d50aee8 0x00100000
530     // --- ---   0 0x00000000 __TEXT LC_SEGMENT 0x000f7000 0x00001000
531     // 0x1d60aee8 0x00001000 --- ---   0 0x00000000 __TEXT
532     //
533     // Any if the user executes the following command:
534     //
535     // (lldb) mem read 0xf6ff0
536     //
537     // We would attempt to read 32 bytes from 0xf6ff0 but would only get 16
538     // unless we loop through consecutive memory ranges that are contiguous in
539     // the address space, but not in the file data.
540     //----------------------------------------------------------------------
541     while (bytes_read < size) {
542       const addr_t curr_addr = addr + bytes_read;
543       const VMRangeToFileOffset::Entry *core_memory_entry =
544           m_core_aranges.FindEntryThatContains(curr_addr);
545 
546       if (core_memory_entry) {
547         const addr_t offset = curr_addr - core_memory_entry->GetRangeBase();
548         const addr_t bytes_left = core_memory_entry->GetRangeEnd() - curr_addr;
549         const size_t bytes_to_read =
550             std::min(size - bytes_read, (size_t)bytes_left);
551         const size_t curr_bytes_read = core_objfile->CopyData(
552             core_memory_entry->data.GetRangeBase() + offset, bytes_to_read,
553             (char *)buf + bytes_read);
554         if (curr_bytes_read == 0)
555           break;
556         bytes_read += curr_bytes_read;
557       } else {
558         // Only set the error if we didn't read any bytes
559         if (bytes_read == 0)
560           error.SetErrorStringWithFormat(
561               "core file does not contain 0x%" PRIx64, curr_addr);
562         break;
563       }
564     }
565   }
566 
567   return bytes_read;
568 }
569 
570 Status ProcessMachCore::GetMemoryRegionInfo(addr_t load_addr,
571                                             MemoryRegionInfo &region_info) {
572   region_info.Clear();
573   const VMRangeToPermissions::Entry *permission_entry =
574       m_core_range_infos.FindEntryThatContainsOrFollows(load_addr);
575   if (permission_entry) {
576     if (permission_entry->Contains(load_addr)) {
577       region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase());
578       region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd());
579       const Flags permissions(permission_entry->data);
580       region_info.SetReadable(permissions.Test(ePermissionsReadable)
581                                   ? MemoryRegionInfo::eYes
582                                   : MemoryRegionInfo::eNo);
583       region_info.SetWritable(permissions.Test(ePermissionsWritable)
584                                   ? MemoryRegionInfo::eYes
585                                   : MemoryRegionInfo::eNo);
586       region_info.SetExecutable(permissions.Test(ePermissionsExecutable)
587                                     ? MemoryRegionInfo::eYes
588                                     : MemoryRegionInfo::eNo);
589       region_info.SetMapped(MemoryRegionInfo::eYes);
590     } else if (load_addr < permission_entry->GetRangeBase()) {
591       region_info.GetRange().SetRangeBase(load_addr);
592       region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase());
593       region_info.SetReadable(MemoryRegionInfo::eNo);
594       region_info.SetWritable(MemoryRegionInfo::eNo);
595       region_info.SetExecutable(MemoryRegionInfo::eNo);
596       region_info.SetMapped(MemoryRegionInfo::eNo);
597     }
598     return Status();
599   }
600 
601   region_info.GetRange().SetRangeBase(load_addr);
602   region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
603   region_info.SetReadable(MemoryRegionInfo::eNo);
604   region_info.SetWritable(MemoryRegionInfo::eNo);
605   region_info.SetExecutable(MemoryRegionInfo::eNo);
606   region_info.SetMapped(MemoryRegionInfo::eNo);
607   return Status();
608 }
609 
610 void ProcessMachCore::Clear() { m_thread_list.Clear(); }
611 
612 void ProcessMachCore::Initialize() {
613   static llvm::once_flag g_once_flag;
614 
615   llvm::call_once(g_once_flag, []() {
616     PluginManager::RegisterPlugin(GetPluginNameStatic(),
617                                   GetPluginDescriptionStatic(), CreateInstance);
618   });
619 }
620 
621 addr_t ProcessMachCore::GetImageInfoAddress() {
622   // If we found both a user-process dyld and a kernel binary, we need to
623   // decide which to prefer.
624   if (GetCorefilePreference() == eKernelCorefile) {
625     if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
626       return m_mach_kernel_addr;
627     }
628     return m_dyld_addr;
629   } else {
630     if (m_dyld_addr != LLDB_INVALID_ADDRESS) {
631       return m_dyld_addr;
632     }
633     return m_mach_kernel_addr;
634   }
635 }
636 
637 lldb_private::ObjectFile *ProcessMachCore::GetCoreObjectFile() {
638   return m_core_module_sp->GetObjectFile();
639 }
640