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