180814287SRaphael Isemann //===-- ProcessMachCore.cpp -----------------------------------------------===//
2c3776bf2SGreg Clayton //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c3776bf2SGreg Clayton //
7c3776bf2SGreg Clayton //===----------------------------------------------------------------------===//
8c3776bf2SGreg Clayton 
976e47d48SRaphael Isemann #include <cerrno>
1076e47d48SRaphael Isemann #include <cstdlib>
11c3776bf2SGreg Clayton 
12c859e2d5SGreg Clayton #include "llvm/Support/MathExtras.h"
13c5f28e2aSKamil Rytarowski #include "llvm/Support/Threading.h"
14c3776bf2SGreg Clayton 
15c3776bf2SGreg Clayton #include "lldb/Core/Debugger.h"
161f746071SGreg Clayton #include "lldb/Core/Module.h"
171f746071SGreg Clayton #include "lldb/Core/ModuleSpec.h"
183385fa08SGreg Clayton #include "lldb/Core/PluginManager.h"
191f746071SGreg Clayton #include "lldb/Core/Section.h"
20c3776bf2SGreg Clayton #include "lldb/Host/Host.h"
21be4be612SJason Molenda #include "lldb/Symbol/LocateSymbolFile.h"
221f746071SGreg Clayton #include "lldb/Symbol/ObjectFile.h"
233385fa08SGreg Clayton #include "lldb/Target/MemoryRegionInfo.h"
2478a14128SJason Molenda #include "lldb/Target/SectionLoadList.h"
25c3776bf2SGreg Clayton #include "lldb/Target/Target.h"
26c3776bf2SGreg Clayton #include "lldb/Target/Thread.h"
27666cc0b2SZachary Turner #include "lldb/Utility/DataBuffer.h"
28c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
296f9e6901SZachary Turner #include "lldb/Utility/Log.h"
30d821c997SPavel Labath #include "lldb/Utility/State.h"
31c3776bf2SGreg Clayton 
32c3776bf2SGreg Clayton #include "ProcessMachCore.h"
332ad48212SJames Y Knight #include "Plugins/Process/Utility/StopInfoMachException.h"
34b9c1b51eSKate Stone #include "ThreadMachCore.h"
35c3776bf2SGreg Clayton 
36a1b5dd9aSGreg Clayton // Needed for the plug-in names for the dynamic loaders.
3777044731SPavel Labath #include "lldb/Host/SafeMachO.h"
3846d005dbSJim Ingham 
39c859e2d5SGreg Clayton #include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
40b9c1b51eSKate Stone #include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h"
4178a14128SJason Molenda #include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"
429cbd3c62SGreg Clayton #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
43c859e2d5SGreg Clayton 
44796ac80bSJonas Devlieghere #include <memory>
45796ac80bSJonas Devlieghere #include <mutex>
46796ac80bSJonas Devlieghere 
47c3776bf2SGreg Clayton using namespace lldb;
48c3776bf2SGreg Clayton using namespace lldb_private;
49c3776bf2SGreg Clayton 
LLDB_PLUGIN_DEFINE(ProcessMachCore)50bba9ba8dSJonas Devlieghere LLDB_PLUGIN_DEFINE(ProcessMachCore)
51fbb4d1e4SJonas Devlieghere 
525f4980f0SPavel Labath llvm::StringRef ProcessMachCore::GetPluginDescriptionStatic() {
53c3776bf2SGreg Clayton   return "Mach-O core file debugging plug-in.";
54c3776bf2SGreg Clayton }
55c3776bf2SGreg Clayton 
Terminate()56b9c1b51eSKate Stone void ProcessMachCore::Terminate() {
57c3776bf2SGreg Clayton   PluginManager::UnregisterPlugin(ProcessMachCore::CreateInstance);
58c3776bf2SGreg Clayton }
59c3776bf2SGreg Clayton 
CreateInstance(lldb::TargetSP target_sp,ListenerSP listener_sp,const FileSpec * crash_file,bool can_connect)60b9c1b51eSKate Stone lldb::ProcessSP ProcessMachCore::CreateInstance(lldb::TargetSP target_sp,
61b9c1b51eSKate Stone                                                 ListenerSP listener_sp,
6218e4272aSMichał Górny                                                 const FileSpec *crash_file,
6318e4272aSMichał Górny                                                 bool can_connect) {
64c3776bf2SGreg Clayton   lldb::ProcessSP process_sp;
6518e4272aSMichał Górny   if (crash_file && !can_connect) {
669cbd3c62SGreg Clayton     const size_t header_size = sizeof(llvm::MachO::mach_header);
6787e403aaSJonas Devlieghere     auto data_sp = FileSystem::Instance().CreateDataBuffer(
6887e403aaSJonas Devlieghere         crash_file->GetPath(), header_size, 0);
69b9c1b51eSKate Stone     if (data_sp && data_sp->GetByteSize() == header_size) {
709cbd3c62SGreg Clayton       DataExtractor data(data_sp, lldb::eByteOrderLittle, 4);
719cbd3c62SGreg Clayton 
729cbd3c62SGreg Clayton       lldb::offset_t data_offset = 0;
739cbd3c62SGreg Clayton       llvm::MachO::mach_header mach_header;
74b9c1b51eSKate Stone       if (ObjectFileMachO::ParseHeader(data, &data_offset, mach_header)) {
759cbd3c62SGreg Clayton         if (mach_header.filetype == llvm::MachO::MH_CORE)
76796ac80bSJonas Devlieghere           process_sp = std::make_shared<ProcessMachCore>(target_sp, listener_sp,
77796ac80bSJonas Devlieghere                                                          *crash_file);
789cbd3c62SGreg Clayton       }
799cbd3c62SGreg Clayton     }
809cbd3c62SGreg Clayton   }
81c3776bf2SGreg Clayton   return process_sp;
82c3776bf2SGreg Clayton }
83c3776bf2SGreg Clayton 
CanDebug(lldb::TargetSP target_sp,bool plugin_specified_by_name)84b9c1b51eSKate Stone bool ProcessMachCore::CanDebug(lldb::TargetSP target_sp,
85b9c1b51eSKate Stone                                bool plugin_specified_by_name) {
86c3776bf2SGreg Clayton   if (plugin_specified_by_name)
87c3776bf2SGreg Clayton     return true;
88c3776bf2SGreg Clayton 
89c3776bf2SGreg Clayton   // For now we are just making sure the file exists for a given module
90dbd7fabaSJonas Devlieghere   if (!m_core_module_sp && FileSystem::Instance().Exists(m_core_file)) {
9105097246SAdrian Prantl     // Don't add the Target's architecture to the ModuleSpec - we may be
9205097246SAdrian Prantl     // working with a core file that doesn't have the correct cpusubtype in the
9305097246SAdrian Prantl     // header but we should still try to use it -
9405097246SAdrian Prantl     // ModuleSpecList::FindMatchingModuleSpec enforces a strict arch mach.
95f37b7c79SJason Molenda     ModuleSpec core_module_spec(m_core_file);
9697206d57SZachary Turner     Status error(ModuleList::GetSharedModule(core_module_spec, m_core_module_sp,
97248a1305SKonrad Kleine                                              nullptr, nullptr, nullptr));
98c3776bf2SGreg Clayton 
99b9c1b51eSKate Stone     if (m_core_module_sp) {
100c3776bf2SGreg Clayton       ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
101c3776bf2SGreg Clayton       if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile)
102c3776bf2SGreg Clayton         return true;
103c3776bf2SGreg Clayton     }
104c3776bf2SGreg Clayton   }
105c3776bf2SGreg Clayton   return false;
106c3776bf2SGreg Clayton }
107c3776bf2SGreg Clayton 
108c3776bf2SGreg Clayton // ProcessMachCore constructor
ProcessMachCore(lldb::TargetSP target_sp,ListenerSP listener_sp,const FileSpec & core_file)109b9c1b51eSKate Stone ProcessMachCore::ProcessMachCore(lldb::TargetSP target_sp,
110b9c1b51eSKate Stone                                  ListenerSP listener_sp,
111b9c1b51eSKate Stone                                  const FileSpec &core_file)
112fb19f11eSWalter Erquinigo     : PostMortemProcess(target_sp, listener_sp), m_core_aranges(),
113fb19f11eSWalter Erquinigo       m_core_range_infos(), m_core_module_sp(), m_core_file(core_file),
114c859e2d5SGreg Clayton       m_dyld_addr(LLDB_INVALID_ADDRESS),
1156fa1b4ffSPavel Labath       m_mach_kernel_addr(LLDB_INVALID_ADDRESS) {}
116c3776bf2SGreg Clayton 
117c3776bf2SGreg Clayton // Destructor
~ProcessMachCore()118b9c1b51eSKate Stone ProcessMachCore::~ProcessMachCore() {
119c3776bf2SGreg Clayton   Clear();
12005097246SAdrian Prantl   // We need to call finalize on the process before destroying ourselves to
12105097246SAdrian Prantl   // make sure all of the broadcaster cleanup goes as planned. If we destruct
12205097246SAdrian Prantl   // this class, then Process::~Process() might have problems trying to fully
12305097246SAdrian Prantl   // destroy the broadcaster.
124c3776bf2SGreg Clayton   Finalize();
125c3776bf2SGreg Clayton }
126c3776bf2SGreg Clayton 
GetDynamicLoaderAddress(lldb::addr_t addr)127b9c1b51eSKate Stone bool ProcessMachCore::GetDynamicLoaderAddress(lldb::addr_t addr) {
128a007a6d8SPavel Labath   Log *log(GetLog(LLDBLog::DynamicLoader | LLDBLog::Process));
129c859e2d5SGreg Clayton   llvm::MachO::mach_header header;
13097206d57SZachary Turner   Status error;
131c859e2d5SGreg Clayton   if (DoReadMemory(addr, &header, sizeof(header), error) != sizeof(header))
132c859e2d5SGreg Clayton     return false;
133510938e5SCharles Davis   if (header.magic == llvm::MachO::MH_CIGAM ||
134b9c1b51eSKate Stone       header.magic == llvm::MachO::MH_CIGAM_64) {
135c859e2d5SGreg Clayton     header.magic = llvm::ByteSwap_32(header.magic);
136c859e2d5SGreg Clayton     header.cputype = llvm::ByteSwap_32(header.cputype);
137c859e2d5SGreg Clayton     header.cpusubtype = llvm::ByteSwap_32(header.cpusubtype);
138c859e2d5SGreg Clayton     header.filetype = llvm::ByteSwap_32(header.filetype);
139c859e2d5SGreg Clayton     header.ncmds = llvm::ByteSwap_32(header.ncmds);
140c859e2d5SGreg Clayton     header.sizeofcmds = llvm::ByteSwap_32(header.sizeofcmds);
141c859e2d5SGreg Clayton     header.flags = llvm::ByteSwap_32(header.flags);
142c859e2d5SGreg Clayton   }
143c859e2d5SGreg Clayton 
144c859e2d5SGreg Clayton   // TODO: swap header if needed...
145b9c1b51eSKate Stone   // printf("0x%16.16" PRIx64 ": magic = 0x%8.8x, file_type= %u\n", vaddr,
146b9c1b51eSKate Stone   // header.magic, header.filetype);
147510938e5SCharles Davis   if (header.magic == llvm::MachO::MH_MAGIC ||
148b9c1b51eSKate Stone       header.magic == llvm::MachO::MH_MAGIC_64) {
14905097246SAdrian Prantl     // Check MH_EXECUTABLE to see if we can find the mach image that contains
15005097246SAdrian Prantl     // the shared library list. The dynamic loader (dyld) is what contains the
15105097246SAdrian Prantl     // list for user applications, and the mach kernel contains a global that
15205097246SAdrian Prantl     // has the list of kexts to load
153b9c1b51eSKate Stone     switch (header.filetype) {
154510938e5SCharles Davis     case llvm::MachO::MH_DYLINKER:
155d01b2953SDaniel Malea       // printf("0x%16.16" PRIx64 ": file_type = MH_DYLINKER\n", vaddr);
156c859e2d5SGreg Clayton       // Address of dyld "struct mach_header" in the core file
15763e5fb76SJonas Devlieghere       LLDB_LOGF(log,
15863e5fb76SJonas Devlieghere                 "ProcessMachCore::GetDynamicLoaderAddress found a user "
159b9c1b51eSKate Stone                 "process dyld binary image at 0x%" PRIx64,
160b9c1b51eSKate Stone                 addr);
161c859e2d5SGreg Clayton       m_dyld_addr = addr;
162c859e2d5SGreg Clayton       return true;
163c859e2d5SGreg Clayton 
164510938e5SCharles Davis     case llvm::MachO::MH_EXECUTE:
165d01b2953SDaniel Malea       // printf("0x%16.16" PRIx64 ": file_type = MH_EXECUTE\n", vaddr);
166c859e2d5SGreg Clayton       // Check MH_EXECUTABLE file types to see if the dynamic link object flag
167c859e2d5SGreg Clayton       // is NOT set. If it isn't, then we have a mach_kernel.
168b9c1b51eSKate Stone       if ((header.flags & llvm::MachO::MH_DYLDLINK) == 0) {
16963e5fb76SJonas Devlieghere         LLDB_LOGF(log,
17063e5fb76SJonas Devlieghere                   "ProcessMachCore::GetDynamicLoaderAddress found a mach "
171b9c1b51eSKate Stone                   "kernel binary image at 0x%" PRIx64,
172b9c1b51eSKate Stone                   addr);
173c859e2d5SGreg Clayton         // Address of the mach kernel "struct mach_header" in the core file.
1747e50d913SJason Molenda         m_mach_kernel_addr = addr;
175c859e2d5SGreg Clayton         return true;
176c859e2d5SGreg Clayton       }
177c859e2d5SGreg Clayton       break;
178c859e2d5SGreg Clayton     }
179c859e2d5SGreg Clayton   }
180c859e2d5SGreg Clayton   return false;
181c859e2d5SGreg Clayton }
182c859e2d5SGreg Clayton 
18378a14128SJason Molenda // We have a hint about a binary -- a UUID, possibly a load address.
18478a14128SJason Molenda // Try to load a file with that UUID into lldb, and if we have a load
18578a14128SJason Molenda // address, set it correctly.  Else assume that the binary was loaded
18678a14128SJason Molenda // with no slide.
load_standalone_binary(UUID uuid,addr_t value,bool value_is_offset,Target & target)187682532caSJason Molenda static bool load_standalone_binary(UUID uuid, addr_t value,
188682532caSJason Molenda                                    bool value_is_offset, Target &target) {
18978a14128SJason Molenda   if (uuid.IsValid()) {
19078a14128SJason Molenda     ModuleSpec module_spec;
19178a14128SJason Molenda     module_spec.GetUUID() = uuid;
19278a14128SJason Molenda 
19378a14128SJason Molenda     // Look up UUID in global module cache before attempting
19478a14128SJason Molenda     // dsymForUUID-like action.
19578a14128SJason Molenda     ModuleSP module_sp;
19678a14128SJason Molenda     Status error = ModuleList::GetSharedModule(module_spec, module_sp, nullptr,
19778a14128SJason Molenda                                                nullptr, nullptr);
19878a14128SJason Molenda 
19978a14128SJason Molenda     if (!module_sp.get()) {
20078a14128SJason Molenda       // Force a a dsymForUUID lookup, if that tool is available.
201*af91446aSJonas Devlieghere       if (!module_spec.GetSymbolFileSpec()) {
202*af91446aSJonas Devlieghere         Status error;
203*af91446aSJonas Devlieghere         Symbols::DownloadObjectAndSymbolFile(module_spec, error, true);
204*af91446aSJonas Devlieghere       }
20578a14128SJason Molenda 
20678a14128SJason Molenda       if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
20778a14128SJason Molenda         module_sp = std::make_shared<Module>(module_spec);
20878a14128SJason Molenda       }
20978a14128SJason Molenda     }
21078a14128SJason Molenda 
211682532caSJason Molenda     // If we couldn't find the binary anywhere else, as a last resort,
212682532caSJason Molenda     // read it out of memory in the corefile.
213682532caSJason Molenda     if (!module_sp.get() && value != LLDB_INVALID_ADDRESS && !value_is_offset) {
214682532caSJason Molenda       char namebuf[80];
215682532caSJason Molenda       snprintf(namebuf, sizeof(namebuf), "mem-image-0x%" PRIx64, value);
216682532caSJason Molenda       module_sp =
217682532caSJason Molenda           target.GetProcessSP()->ReadModuleFromMemory(FileSpec(namebuf), value);
218682532caSJason Molenda     }
219682532caSJason Molenda 
220682532caSJason Molenda     if (module_sp.get()) {
22178a14128SJason Molenda       target.SetArchitecture(module_sp->GetObjectFile()->GetArchitecture());
22278a14128SJason Molenda       target.GetImages().AppendIfNeeded(module_sp, false);
22378a14128SJason Molenda 
2249a8a0a38SJason Molenda       // TODO: Instead of using the load address as a value, if we create a
2259a8a0a38SJason Molenda       // memory module from that address, we could get the correct segment
2269a8a0a38SJason Molenda       // offset values from the in-memory load commands and set them correctly.
2279a8a0a38SJason Molenda       // In case the load address we were given is not correct for all segments,
2289a8a0a38SJason Molenda       // e.g. something in the shared cache.  DynamicLoaderDarwinKernel does
2299a8a0a38SJason Molenda       // something similar for kexts.  In the context of a corefile, this would
2309a8a0a38SJason Molenda       // be an inexpensive operation.  Not all binaries in a corefile will have
2319a8a0a38SJason Molenda       // a Mach-O header/load commands in memory, so this will not work in all
2329a8a0a38SJason Molenda       // cases.
2339a8a0a38SJason Molenda 
23478a14128SJason Molenda       bool changed = false;
235682532caSJason Molenda       if (module_sp->GetObjectFile()) {
236682532caSJason Molenda         if (value != LLDB_INVALID_ADDRESS) {
237682532caSJason Molenda           module_sp->SetLoadAddress(target, value, value_is_offset, changed);
238682532caSJason Molenda         } else {
239682532caSJason Molenda           // No address/offset/slide, load the binary at file address,
240682532caSJason Molenda           // offset 0.
241682532caSJason Molenda           const bool value_is_slide = true;
242682532caSJason Molenda           module_sp->SetLoadAddress(target, 0, value_is_slide, changed);
243682532caSJason Molenda         }
244682532caSJason Molenda       } else {
245682532caSJason Molenda         // In-memory image, load at its true address, offset 0.
246682532caSJason Molenda         const bool value_is_slide = true;
247682532caSJason Molenda         module_sp->SetLoadAddress(target, 0, value_is_slide, changed);
248682532caSJason Molenda       }
24978a14128SJason Molenda 
25078a14128SJason Molenda       ModuleList added_module;
25178a14128SJason Molenda       added_module.Append(module_sp, false);
25278a14128SJason Molenda       target.ModulesDidLoad(added_module);
25378a14128SJason Molenda 
25478a14128SJason Molenda       // Flush info in the process (stack frames, etc).
25578a14128SJason Molenda       ProcessSP process_sp(target.GetProcessSP());
25678a14128SJason Molenda       if (process_sp)
25778a14128SJason Molenda         process_sp->Flush();
25878a14128SJason Molenda 
25978a14128SJason Molenda       return true;
26078a14128SJason Molenda     }
26178a14128SJason Molenda   }
26278a14128SJason Molenda   return false;
26378a14128SJason Molenda }
26478a14128SJason Molenda 
265c3776bf2SGreg Clayton // Process Control
DoLoadCore()26697206d57SZachary Turner Status ProcessMachCore::DoLoadCore() {
267a007a6d8SPavel Labath   Log *log(GetLog(LLDBLog::DynamicLoader | LLDBLog::Process));
26897206d57SZachary Turner   Status error;
269b9c1b51eSKate Stone   if (!m_core_module_sp) {
270c859e2d5SGreg Clayton     error.SetErrorString("invalid core module");
271c859e2d5SGreg Clayton     return error;
272c859e2d5SGreg Clayton   }
273c859e2d5SGreg Clayton 
274c3776bf2SGreg Clayton   ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
275248a1305SKonrad Kleine   if (core_objfile == nullptr) {
276c3776bf2SGreg Clayton     error.SetErrorString("invalid core object file");
277c3776bf2SGreg Clayton     return error;
278c3776bf2SGreg Clayton   }
2799645e82cSGreg Clayton 
280b9c1b51eSKate Stone   if (core_objfile->GetNumThreadContexts() == 0) {
281b9c1b51eSKate Stone     error.SetErrorString("core file doesn't contain any LC_THREAD load "
282b9c1b51eSKate Stone                          "commands, or the LC_THREAD architecture is not "
283b9c1b51eSKate Stone                          "supported in this lldb");
2849645e82cSGreg Clayton     return error;
2859645e82cSGreg Clayton   }
2869645e82cSGreg Clayton 
287c3776bf2SGreg Clayton   SectionList *section_list = core_objfile->GetSectionList();
288248a1305SKonrad Kleine   if (section_list == nullptr) {
289c3776bf2SGreg Clayton     error.SetErrorString("core file has no sections");
290c3776bf2SGreg Clayton     return error;
291c3776bf2SGreg Clayton   }
292c3776bf2SGreg Clayton 
293c3776bf2SGreg Clayton   const uint32_t num_sections = section_list->GetNumSections(0);
294b9c1b51eSKate Stone   if (num_sections == 0) {
295c3776bf2SGreg Clayton     error.SetErrorString("core file has no sections");
296c3776bf2SGreg Clayton     return error;
297c3776bf2SGreg Clayton   }
298c859e2d5SGreg Clayton 
299bb860bd2SJason Molenda   SetCanJIT(false);
300bb860bd2SJason Molenda 
301c859e2d5SGreg Clayton   llvm::MachO::mach_header header;
302b9c1b51eSKate Stone   DataExtractor data(&header, sizeof(header),
303c859e2d5SGreg Clayton                      m_core_module_sp->GetArchitecture().GetByteOrder(),
304c859e2d5SGreg Clayton                      m_core_module_sp->GetArchitecture().GetAddressByteSize());
305c859e2d5SGreg Clayton 
306c3776bf2SGreg Clayton   bool ranges_are_sorted = true;
307c3776bf2SGreg Clayton   addr_t vm_addr = 0;
308b9c1b51eSKate Stone   for (uint32_t i = 0; i < num_sections; ++i) {
309c3776bf2SGreg Clayton     Section *section = section_list->GetSectionAtIndex(i).get();
31062d91638SJason Molenda     if (section && section->GetFileSize() > 0) {
311c3776bf2SGreg Clayton       lldb::addr_t section_vm_addr = section->GetFileAddress();
312c3776bf2SGreg Clayton       FileRange file_range(section->GetFileOffset(), section->GetFileSize());
313b9c1b51eSKate Stone       VMRangeToFileOffset::Entry range_entry(
314b9c1b51eSKate Stone           section_vm_addr, section->GetByteSize(), file_range);
315c3776bf2SGreg Clayton 
316c3776bf2SGreg Clayton       if (vm_addr > section_vm_addr)
317c3776bf2SGreg Clayton         ranges_are_sorted = false;
318c3776bf2SGreg Clayton       vm_addr = section->GetFileAddress();
319c3776bf2SGreg Clayton       VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
320c859e2d5SGreg Clayton 
321c3776bf2SGreg Clayton       if (last_entry &&
322c3776bf2SGreg Clayton           last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
323b9c1b51eSKate Stone           last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase()) {
324c3776bf2SGreg Clayton         last_entry->SetRangeEnd(range_entry.GetRangeEnd());
325c3776bf2SGreg Clayton         last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd());
326b9c1b51eSKate Stone       } else {
327c3776bf2SGreg Clayton         m_core_aranges.Append(range_entry);
328c3776bf2SGreg Clayton       }
32905097246SAdrian Prantl       // Some core files don't fill in the permissions correctly. If that is
33005097246SAdrian Prantl       // the case assume read + execute so clients don't think the memory is
33105097246SAdrian Prantl       // not readable, or executable. The memory isn't writable since this
33205097246SAdrian Prantl       // plug-in doesn't implement DoWriteMemory.
33300b385e3SGreg Clayton       uint32_t permissions = section->GetPermissions();
33400b385e3SGreg Clayton       if (permissions == 0)
33500b385e3SGreg Clayton         permissions = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;
336b9c1b51eSKate Stone       m_core_range_infos.Append(VMRangeToPermissions::Entry(
337b9c1b51eSKate Stone           section_vm_addr, section->GetByteSize(), permissions));
338c3776bf2SGreg Clayton     }
339c3776bf2SGreg Clayton   }
340b9c1b51eSKate Stone   if (!ranges_are_sorted) {
341c3776bf2SGreg Clayton     m_core_aranges.Sort();
3423385fa08SGreg Clayton     m_core_range_infos.Sort();
343c3776bf2SGreg Clayton   }
344c859e2d5SGreg Clayton 
3453533cec5SJason Molenda   bool found_main_binary_definitively = false;
3463533cec5SJason Molenda 
347682532caSJason Molenda   addr_t objfile_binary_value;
348682532caSJason Molenda   bool objfile_binary_value_is_offset;
3499b7fcdcbSJason Molenda   UUID objfile_binary_uuid;
3501bec6eb3SJason Molenda   ObjectFile::BinaryType type;
351682532caSJason Molenda   if (core_objfile->GetCorefileMainBinaryInfo(objfile_binary_value,
352682532caSJason Molenda                                               objfile_binary_value_is_offset,
3531bec6eb3SJason Molenda                                               objfile_binary_uuid, type)) {
35478a14128SJason Molenda     if (log) {
35578a14128SJason Molenda       log->Printf(
35678a14128SJason Molenda           "ProcessMachCore::DoLoadCore: using binary hint from 'main bin spec' "
357682532caSJason Molenda           "LC_NOTE with UUID %s value 0x%" PRIx64
358682532caSJason Molenda           " value is offset %d and type %d",
359682532caSJason Molenda           objfile_binary_uuid.GetAsString().c_str(), objfile_binary_value,
360682532caSJason Molenda           objfile_binary_value_is_offset, type);
36178a14128SJason Molenda     }
362682532caSJason Molenda     if (objfile_binary_value != LLDB_INVALID_ADDRESS &&
363682532caSJason Molenda         !objfile_binary_value_is_offset) {
36478a14128SJason Molenda       if (type == ObjectFile::eBinaryTypeUser) {
3659a8a0a38SJason Molenda         load_standalone_binary(objfile_binary_uuid, objfile_binary_value,
3669a8a0a38SJason Molenda                                objfile_binary_value_is_offset, GetTarget());
367682532caSJason Molenda         m_dyld_addr = objfile_binary_value;
36878a14128SJason Molenda         m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
3699b7fcdcbSJason Molenda         found_main_binary_definitively = true;
37078a14128SJason Molenda       }
37178a14128SJason Molenda       if (type == ObjectFile::eBinaryTypeKernel) {
372682532caSJason Molenda         m_mach_kernel_addr = objfile_binary_value;
37378a14128SJason Molenda         m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
37478a14128SJason Molenda         found_main_binary_definitively = true;
37578a14128SJason Molenda       }
37678a14128SJason Molenda     }
37778a14128SJason Molenda     if (!found_main_binary_definitively) {
37878a14128SJason Molenda       // ObjectFile::eBinaryTypeStandalone, undeclared types
379682532caSJason Molenda       if (load_standalone_binary(objfile_binary_uuid, objfile_binary_value,
380682532caSJason Molenda                                  objfile_binary_value_is_offset, GetTarget())) {
38178a14128SJason Molenda         found_main_binary_definitively = true;
38278a14128SJason Molenda         m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic();
38378a14128SJason Molenda       }
3849b7fcdcbSJason Molenda     }
3859b7fcdcbSJason Molenda   }
3869b7fcdcbSJason Molenda 
3873533cec5SJason Molenda   // This checks for the presence of an LC_IDENT string in a core file;
38805097246SAdrian Prantl   // LC_IDENT is very obsolete and should not be used in new code, but if the
38905097246SAdrian Prantl   // load command is present, let's use the contents.
39078a14128SJason Molenda   UUID ident_uuid;
39178a14128SJason Molenda   addr_t ident_binary_addr = LLDB_INVALID_ADDRESS;
39278a14128SJason Molenda   if (!found_main_binary_definitively) {
3933533cec5SJason Molenda     std::string corefile_identifier = core_objfile->GetIdentifierString();
39478a14128SJason Molenda 
39578a14128SJason Molenda     // Search for UUID= and stext= strings in the identifier str.
3963533cec5SJason Molenda     if (corefile_identifier.find("UUID=") != std::string::npos) {
3973533cec5SJason Molenda       size_t p = corefile_identifier.find("UUID=") + strlen("UUID=");
3983533cec5SJason Molenda       std::string uuid_str = corefile_identifier.substr(p, 36);
39978a14128SJason Molenda       ident_uuid.SetFromStringRef(uuid_str);
40078a14128SJason Molenda       if (log)
40178a14128SJason Molenda         log->Printf("Got a UUID from LC_IDENT/kern ver str LC_NOTE: %s",
40278a14128SJason Molenda                     ident_uuid.GetAsString().c_str());
4033533cec5SJason Molenda     }
4043533cec5SJason Molenda     if (corefile_identifier.find("stext=") != std::string::npos) {
4053533cec5SJason Molenda       size_t p = corefile_identifier.find("stext=") + strlen("stext=");
4063533cec5SJason Molenda       if (corefile_identifier[p] == '0' && corefile_identifier[p + 1] == 'x') {
40778a14128SJason Molenda         ident_binary_addr =
40878a14128SJason Molenda             ::strtoul(corefile_identifier.c_str() + p, nullptr, 16);
40978a14128SJason Molenda         if (log)
41078a14128SJason Molenda           log->Printf("Got a load address from LC_IDENT/kern ver str "
41178a14128SJason Molenda                       "LC_NOTE: 0x%" PRIx64,
41278a14128SJason Molenda                       ident_binary_addr);
4133533cec5SJason Molenda       }
4143533cec5SJason Molenda     }
41578a14128SJason Molenda 
41678a14128SJason Molenda     // Search for a "Darwin Kernel" str indicating kernel; else treat as
41778a14128SJason Molenda     // standalone
41878a14128SJason Molenda     if (corefile_identifier.find("Darwin Kernel") != std::string::npos &&
41978a14128SJason Molenda         ident_uuid.IsValid() && ident_binary_addr != LLDB_INVALID_ADDRESS) {
42078a14128SJason Molenda       if (log)
42178a14128SJason Molenda         log->Printf("ProcessMachCore::DoLoadCore: Found kernel binary via "
42278a14128SJason Molenda                     "LC_IDENT/kern ver str LC_NOTE");
42378a14128SJason Molenda       m_mach_kernel_addr = ident_binary_addr;
4243533cec5SJason Molenda       found_main_binary_definitively = true;
42578a14128SJason Molenda     } else if (ident_uuid.IsValid()) {
426682532caSJason Molenda       // We have no address specified, only a UUID.  Load it at the file
427682532caSJason Molenda       // address.
428682532caSJason Molenda       const bool value_is_offset = false;
429682532caSJason Molenda       if (load_standalone_binary(ident_uuid, ident_binary_addr, value_is_offset,
430682532caSJason Molenda                                  GetTarget())) {
4311bec6eb3SJason Molenda         found_main_binary_definitively = true;
43278a14128SJason Molenda         m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic();
433be4be612SJason Molenda       }
434be4be612SJason Molenda     }
435be4be612SJason Molenda   }
4363533cec5SJason Molenda 
437682532caSJason Molenda   bool did_load_extra_binaries = core_objfile->LoadCoreFileImages(*this);
4389ea6dd5cSJason Molenda   // If we have a "all image infos" LC_NOTE, try to load all of the
4399ea6dd5cSJason Molenda   // binaries listed, and set their Section load addresses in the Target.
440682532caSJason Molenda   if (found_main_binary_definitively == false && did_load_extra_binaries) {
4419ea6dd5cSJason Molenda     m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
4429ea6dd5cSJason Molenda     found_main_binary_definitively = true;
4439ea6dd5cSJason Molenda   }
4449ea6dd5cSJason Molenda 
445a6682a41SJonas Devlieghere   if (!found_main_binary_definitively &&
446a6682a41SJonas Devlieghere       (m_dyld_addr == LLDB_INVALID_ADDRESS ||
447a6682a41SJonas Devlieghere        m_mach_kernel_addr == LLDB_INVALID_ADDRESS)) {
44805097246SAdrian Prantl     // We need to locate the main executable in the memory ranges we have in
44905097246SAdrian Prantl     // the core file.  We need to search for both a user-process dyld binary
450b9c1b51eSKate Stone     // and a kernel binary in memory; we must look at all the pages in the
45105097246SAdrian Prantl     // binary so we don't miss one or the other.  Step through all memory
45205097246SAdrian Prantl     // segments searching for a kernel binary and for a user process dyld --
45305097246SAdrian Prantl     // we'll decide which to prefer later if both are present.
45492ee75c0SJason Molenda 
4557e50d913SJason Molenda     const size_t num_core_aranges = m_core_aranges.GetSize();
456b9c1b51eSKate Stone     for (size_t i = 0; i < num_core_aranges; ++i) {
457b9c1b51eSKate Stone       const VMRangeToFileOffset::Entry *entry =
458b9c1b51eSKate Stone           m_core_aranges.GetEntryAtIndex(i);
4597e50d913SJason Molenda       lldb::addr_t section_vm_addr_start = entry->GetRangeBase();
4607e50d913SJason Molenda       lldb::addr_t section_vm_addr_end = entry->GetRangeEnd();
4617e50d913SJason Molenda       for (lldb::addr_t section_vm_addr = section_vm_addr_start;
462b9c1b51eSKate Stone            section_vm_addr < section_vm_addr_end; section_vm_addr += 0x1000) {
4637e50d913SJason Molenda         GetDynamicLoaderAddress(section_vm_addr);
4647e50d913SJason Molenda       }
4657e50d913SJason Molenda     }
4667e50d913SJason Molenda   }
4677e50d913SJason Molenda 
468a6682a41SJonas Devlieghere   if (!found_main_binary_definitively &&
469a6682a41SJonas Devlieghere       m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
470b9c1b51eSKate Stone     // In the case of multiple kernel images found in the core file via
47105097246SAdrian Prantl     // exhaustive search, we may not pick the correct one.  See if the
47205097246SAdrian Prantl     // DynamicLoaderDarwinKernel's search heuristics might identify the correct
47305097246SAdrian Prantl     // one. Most of the time, I expect the address from SearchForDarwinKernel()
47405097246SAdrian Prantl     // will be the same as the address we found via exhaustive search.
475880988afSJason Molenda 
476a6682a41SJonas Devlieghere     if (!GetTarget().GetArchitecture().IsValid() && m_core_module_sp.get()) {
477880988afSJason Molenda       GetTarget().SetArchitecture(m_core_module_sp->GetArchitecture());
478880988afSJason Molenda     }
479880988afSJason Molenda 
480b9c1b51eSKate Stone     // SearchForDarwinKernel will end up calling back into this this class in
48105097246SAdrian Prantl     // the GetImageInfoAddress method which will give it the
48205097246SAdrian Prantl     // m_mach_kernel_addr/m_dyld_addr it already has.  Save that aside and set
48305097246SAdrian Prantl     // m_mach_kernel_addr/m_dyld_addr to an invalid address temporarily so
48405097246SAdrian Prantl     // DynamicLoaderDarwinKernel does a real search for the kernel using its
48505097246SAdrian Prantl     // own heuristics.
4865f826bbcSJason Molenda 
487880988afSJason Molenda     addr_t saved_mach_kernel_addr = m_mach_kernel_addr;
4885f826bbcSJason Molenda     addr_t saved_user_dyld_addr = m_dyld_addr;
489880988afSJason Molenda     m_mach_kernel_addr = LLDB_INVALID_ADDRESS;
4905f826bbcSJason Molenda     m_dyld_addr = LLDB_INVALID_ADDRESS;
4915f826bbcSJason Molenda 
492b9c1b51eSKate Stone     addr_t better_kernel_address =
493b9c1b51eSKate Stone         DynamicLoaderDarwinKernel::SearchForDarwinKernel(this);
4945f826bbcSJason Molenda 
495880988afSJason Molenda     m_mach_kernel_addr = saved_mach_kernel_addr;
4965f826bbcSJason Molenda     m_dyld_addr = saved_user_dyld_addr;
4975f826bbcSJason Molenda 
498b9c1b51eSKate Stone     if (better_kernel_address != LLDB_INVALID_ADDRESS) {
49963e5fb76SJonas Devlieghere       LLDB_LOGF(log, "ProcessMachCore::DoLoadCore: Using the kernel address "
500b9c1b51eSKate Stone                      "from DynamicLoaderDarwinKernel");
501880988afSJason Molenda       m_mach_kernel_addr = better_kernel_address;
502880988afSJason Molenda     }
503880988afSJason Molenda   }
504880988afSJason Molenda 
5056fa1b4ffSPavel Labath   if (m_dyld_plugin_name.empty()) {
50605097246SAdrian Prantl     // If we found both a user-process dyld and a kernel binary, we need to
50705097246SAdrian Prantl     // decide which to prefer.
508b9c1b51eSKate Stone     if (GetCorefilePreference() == eKernelCorefile) {
509b9c1b51eSKate Stone       if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
51063e5fb76SJonas Devlieghere         LLDB_LOGF(log,
51163e5fb76SJonas Devlieghere                   "ProcessMachCore::DoLoadCore: Using kernel corefile image "
512b9c1b51eSKate Stone                   "at 0x%" PRIx64,
513b9c1b51eSKate Stone                   m_mach_kernel_addr);
5147e50d913SJason Molenda         m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
515b9c1b51eSKate Stone       } else if (m_dyld_addr != LLDB_INVALID_ADDRESS) {
51663e5fb76SJonas Devlieghere         LLDB_LOGF(log,
51763e5fb76SJonas Devlieghere                   "ProcessMachCore::DoLoadCore: Using user process dyld "
518b9c1b51eSKate Stone                   "image at 0x%" PRIx64,
519b9c1b51eSKate Stone                   m_dyld_addr);
520eadd2cb4SJason Molenda         m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
521eadd2cb4SJason Molenda       }
522b9c1b51eSKate Stone     } else {
523b9c1b51eSKate Stone       if (m_dyld_addr != LLDB_INVALID_ADDRESS) {
52463e5fb76SJonas Devlieghere         LLDB_LOGF(log,
52563e5fb76SJonas Devlieghere                   "ProcessMachCore::DoLoadCore: Using user process dyld "
526b9c1b51eSKate Stone                   "image at 0x%" PRIx64,
527b9c1b51eSKate Stone                   m_dyld_addr);
528703a4561SJason Molenda         m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
529b9c1b51eSKate Stone       } else if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
53063e5fb76SJonas Devlieghere         LLDB_LOGF(log,
53163e5fb76SJonas Devlieghere                   "ProcessMachCore::DoLoadCore: Using kernel corefile image "
532b9c1b51eSKate Stone                   "at 0x%" PRIx64,
533b9c1b51eSKate Stone                   m_mach_kernel_addr);
534703a4561SJason Molenda         m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
535703a4561SJason Molenda       }
536703a4561SJason Molenda     }
5371bec6eb3SJason Molenda   }
5387e50d913SJason Molenda 
539b9c1b51eSKate Stone   if (m_dyld_plugin_name != DynamicLoaderMacOSXDYLD::GetPluginNameStatic()) {
540b9c1b51eSKate Stone     // For non-user process core files, the permissions on the core file
54105097246SAdrian Prantl     // segments are usually meaningless, they may be just "read", because we're
54205097246SAdrian Prantl     // dealing with kernel coredumps or early startup coredumps and the dumper
54305097246SAdrian Prantl     // is grabbing pages of memory without knowing what they are.  If they
544e9264b74SKazuaki Ishizaki     // aren't marked as "executable", that can break the unwinder which will
54505097246SAdrian Prantl     // check a pc value to see if it is in an executable segment and stop the
546b9c1b51eSKate Stone     // backtrace early if it is not ("executable" and "unknown" would both be
54705097246SAdrian Prantl     // fine, but "not executable" will break the unwinder).
5484fa50412SJason Molenda     size_t core_range_infos_size = m_core_range_infos.GetSize();
549b9c1b51eSKate Stone     for (size_t i = 0; i < core_range_infos_size; i++) {
550b9c1b51eSKate Stone       VMRangeToPermissions::Entry *ent =
551b9c1b51eSKate Stone           m_core_range_infos.GetMutableEntryAtIndex(i);
5524fa50412SJason Molenda       ent->data = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;
5534fa50412SJason Molenda     }
5544fa50412SJason Molenda   }
5554fa50412SJason Molenda 
55605097246SAdrian Prantl   // Even if the architecture is set in the target, we need to override it to
55705097246SAdrian Prantl   // match the core file which is always single arch.
558c859e2d5SGreg Clayton   ArchSpec arch(m_core_module_sp->GetArchitecture());
559b9c1b51eSKate Stone   if (arch.GetCore() == ArchSpec::eCore_x86_32_i486) {
560e4435642SPavel Labath     arch = Platform::GetAugmentedArchSpec(GetTarget().GetPlatform().get(), "i386");
561c859e2d5SGreg Clayton   }
562c859e2d5SGreg Clayton   if (arch.IsValid())
5637529df9aSZachary Turner     GetTarget().SetArchitecture(arch);
564c859e2d5SGreg Clayton 
565cdc6f8d7SJason Molenda   addr_t address_mask = core_objfile->GetAddressMask();
566cdc6f8d7SJason Molenda   if (address_mask != 0) {
567cdc6f8d7SJason Molenda     SetCodeAddressMask(address_mask);
568cdc6f8d7SJason Molenda     SetDataAddressMask(address_mask);
569cdc6f8d7SJason Molenda   }
570c3776bf2SGreg Clayton   return error;
571c3776bf2SGreg Clayton }
572c3776bf2SGreg Clayton 
GetDynamicLoader()573b9c1b51eSKate Stone lldb_private::DynamicLoader *ProcessMachCore::GetDynamicLoader() {
574248a1305SKonrad Kleine   if (m_dyld_up.get() == nullptr)
5756fa1b4ffSPavel Labath     m_dyld_up.reset(DynamicLoader::FindPlugin(this, m_dyld_plugin_name));
576d5b44036SJonas Devlieghere   return m_dyld_up.get();
577c859e2d5SGreg Clayton }
578c3776bf2SGreg Clayton 
DoUpdateThreadList(ThreadList & old_thread_list,ThreadList & new_thread_list)5794bb62448SWalter Erquinigo bool ProcessMachCore::DoUpdateThreadList(ThreadList &old_thread_list,
580b9c1b51eSKate Stone                                          ThreadList &new_thread_list) {
581b9c1b51eSKate Stone   if (old_thread_list.GetSize(false) == 0) {
582b9c1b51eSKate Stone     // Make up the thread the first time this is called so we can setup our one
58305097246SAdrian Prantl     // and only core thread state.
584c3776bf2SGreg Clayton     ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
585c3776bf2SGreg Clayton 
586b9c1b51eSKate Stone     if (core_objfile) {
587c3776bf2SGreg Clayton       const uint32_t num_threads = core_objfile->GetNumThreadContexts();
588b9c1b51eSKate Stone       for (lldb::tid_t tid = 0; tid < num_threads; ++tid) {
5894f465cffSJim Ingham         ThreadSP thread_sp(new ThreadMachCore(*this, tid));
590c3776bf2SGreg Clayton         new_thread_list.AddThread(thread_sp);
591c3776bf2SGreg Clayton       }
592c3776bf2SGreg Clayton     }
593b9c1b51eSKate Stone   } else {
594c3776bf2SGreg Clayton     const uint32_t num_threads = old_thread_list.GetSize(false);
595c3776bf2SGreg Clayton     for (uint32_t i = 0; i < num_threads; ++i)
596332e8b1cSGreg Clayton       new_thread_list.AddThread(old_thread_list.GetThreadAtIndex(i, false));
597c3776bf2SGreg Clayton   }
5989fc13556SGreg Clayton   return new_thread_list.GetSize(false) > 0;
599c3776bf2SGreg Clayton }
600c3776bf2SGreg Clayton 
RefreshStateAfterStop()601b9c1b51eSKate Stone void ProcessMachCore::RefreshStateAfterStop() {
60205097246SAdrian Prantl   // Let all threads recover from stopping and do any clean up based on the
60305097246SAdrian Prantl   // previous thread state (if any).
604c3776bf2SGreg Clayton   m_thread_list.RefreshStateAfterStop();
605c3776bf2SGreg Clayton   // SetThreadStopInfo (m_last_stop_packet);
606c3776bf2SGreg Clayton }
607c3776bf2SGreg Clayton 
DoDestroy()60897206d57SZachary Turner Status ProcessMachCore::DoDestroy() { return Status(); }
609c3776bf2SGreg Clayton 
610c3776bf2SGreg Clayton // Process Queries
611c3776bf2SGreg Clayton 
IsAlive()612b9c1b51eSKate Stone bool ProcessMachCore::IsAlive() { return true; }
613c3776bf2SGreg Clayton 
WarnBeforeDetach() const614b9c1b51eSKate Stone bool ProcessMachCore::WarnBeforeDetach() const { return false; }
615408fa333SJason Molenda 
616c3776bf2SGreg Clayton // Process Memory
ReadMemory(addr_t addr,void * buf,size_t size,Status & error)617b9c1b51eSKate Stone size_t ProcessMachCore::ReadMemory(addr_t addr, void *buf, size_t size,
61897206d57SZachary Turner                                    Status &error) {
61905097246SAdrian Prantl   // Don't allow the caching that lldb_private::Process::ReadMemory does since
62005097246SAdrian Prantl   // in core files we have it all cached our our core file anyway.
621c859e2d5SGreg Clayton   return DoReadMemory(addr, buf, size, error);
622c859e2d5SGreg Clayton }
623c859e2d5SGreg Clayton 
DoReadMemory(addr_t addr,void * buf,size_t size,Status & error)624b9c1b51eSKate Stone size_t ProcessMachCore::DoReadMemory(addr_t addr, void *buf, size_t size,
62597206d57SZachary Turner                                      Status &error) {
626c3776bf2SGreg Clayton   ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
62760adaf53SGreg Clayton   size_t bytes_read = 0;
628c3776bf2SGreg Clayton 
629b9c1b51eSKate Stone   if (core_objfile) {
63060adaf53SGreg Clayton     // Segments are not always contiguous in mach-o core files. We have core
63160adaf53SGreg Clayton     // files that have segments like:
63260adaf53SGreg Clayton     //            Address    Size       File off   File size
63360adaf53SGreg Clayton     //            ---------- ---------- ---------- ----------
634b9c1b51eSKate Stone     // LC_SEGMENT 0x000f6000 0x00001000 0x1d509ee8 0x00001000 --- ---   0
63505097246SAdrian Prantl     // 0x00000000 __TEXT LC_SEGMENT 0x0f600000 0x00100000 0x1d50aee8 0x00100000
63605097246SAdrian Prantl     // --- ---   0 0x00000000 __TEXT LC_SEGMENT 0x000f7000 0x00001000
63705097246SAdrian Prantl     // 0x1d60aee8 0x00001000 --- ---   0 0x00000000 __TEXT
63860adaf53SGreg Clayton     //
63960adaf53SGreg Clayton     // Any if the user executes the following command:
64060adaf53SGreg Clayton     //
64160adaf53SGreg Clayton     // (lldb) mem read 0xf6ff0
64260adaf53SGreg Clayton     //
64305097246SAdrian Prantl     // We would attempt to read 32 bytes from 0xf6ff0 but would only get 16
64405097246SAdrian Prantl     // unless we loop through consecutive memory ranges that are contiguous in
64505097246SAdrian Prantl     // the address space, but not in the file data.
646b9c1b51eSKate Stone     while (bytes_read < size) {
64760adaf53SGreg Clayton       const addr_t curr_addr = addr + bytes_read;
648b9c1b51eSKate Stone       const VMRangeToFileOffset::Entry *core_memory_entry =
649b9c1b51eSKate Stone           m_core_aranges.FindEntryThatContains(curr_addr);
65060adaf53SGreg Clayton 
651b9c1b51eSKate Stone       if (core_memory_entry) {
65260adaf53SGreg Clayton         const addr_t offset = curr_addr - core_memory_entry->GetRangeBase();
65360adaf53SGreg Clayton         const addr_t bytes_left = core_memory_entry->GetRangeEnd() - curr_addr;
654b9c1b51eSKate Stone         const size_t bytes_to_read =
655b9c1b51eSKate Stone             std::min(size - bytes_read, (size_t)bytes_left);
656b9c1b51eSKate Stone         const size_t curr_bytes_read = core_objfile->CopyData(
657b9c1b51eSKate Stone             core_memory_entry->data.GetRangeBase() + offset, bytes_to_read,
658b9c1b51eSKate Stone             (char *)buf + bytes_read);
65960adaf53SGreg Clayton         if (curr_bytes_read == 0)
66060adaf53SGreg Clayton           break;
66160adaf53SGreg Clayton         bytes_read += curr_bytes_read;
662b9c1b51eSKate Stone       } else {
66360adaf53SGreg Clayton         // Only set the error if we didn't read any bytes
66460adaf53SGreg Clayton         if (bytes_read == 0)
665b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
666b9c1b51eSKate Stone               "core file does not contain 0x%" PRIx64, curr_addr);
66760adaf53SGreg Clayton         break;
668c3776bf2SGreg Clayton       }
669c3776bf2SGreg Clayton     }
67060adaf53SGreg Clayton   }
67160adaf53SGreg Clayton 
67260adaf53SGreg Clayton   return bytes_read;
673c3776bf2SGreg Clayton }
674c3776bf2SGreg Clayton 
DoGetMemoryRegionInfo(addr_t load_addr,MemoryRegionInfo & region_info)6752937b282SDavid Spickett Status ProcessMachCore::DoGetMemoryRegionInfo(addr_t load_addr,
676b9c1b51eSKate Stone                                               MemoryRegionInfo &region_info) {
6773385fa08SGreg Clayton   region_info.Clear();
678b9c1b51eSKate Stone   const VMRangeToPermissions::Entry *permission_entry =
679b9c1b51eSKate Stone       m_core_range_infos.FindEntryThatContainsOrFollows(load_addr);
680b9c1b51eSKate Stone   if (permission_entry) {
681b9c1b51eSKate Stone     if (permission_entry->Contains(load_addr)) {
6823385fa08SGreg Clayton       region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase());
6833385fa08SGreg Clayton       region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd());
6843385fa08SGreg Clayton       const Flags permissions(permission_entry->data);
685b9c1b51eSKate Stone       region_info.SetReadable(permissions.Test(ePermissionsReadable)
686b9c1b51eSKate Stone                                   ? MemoryRegionInfo::eYes
6873385fa08SGreg Clayton                                   : MemoryRegionInfo::eNo);
688b9c1b51eSKate Stone       region_info.SetWritable(permissions.Test(ePermissionsWritable)
689b9c1b51eSKate Stone                                   ? MemoryRegionInfo::eYes
6903385fa08SGreg Clayton                                   : MemoryRegionInfo::eNo);
691b9c1b51eSKate Stone       region_info.SetExecutable(permissions.Test(ePermissionsExecutable)
692b9c1b51eSKate Stone                                     ? MemoryRegionInfo::eYes
6933385fa08SGreg Clayton                                     : MemoryRegionInfo::eNo);
694ad007563SHoward Hellyer       region_info.SetMapped(MemoryRegionInfo::eYes);
695b9c1b51eSKate Stone     } else if (load_addr < permission_entry->GetRangeBase()) {
6963385fa08SGreg Clayton       region_info.GetRange().SetRangeBase(load_addr);
6973385fa08SGreg Clayton       region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase());
6983385fa08SGreg Clayton       region_info.SetReadable(MemoryRegionInfo::eNo);
6993385fa08SGreg Clayton       region_info.SetWritable(MemoryRegionInfo::eNo);
7003385fa08SGreg Clayton       region_info.SetExecutable(MemoryRegionInfo::eNo);
701ad007563SHoward Hellyer       region_info.SetMapped(MemoryRegionInfo::eNo);
7023385fa08SGreg Clayton     }
70397206d57SZachary Turner     return Status();
7043385fa08SGreg Clayton   }
7053385fa08SGreg Clayton 
706ad007563SHoward Hellyer   region_info.GetRange().SetRangeBase(load_addr);
707ad007563SHoward Hellyer   region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
708ad007563SHoward Hellyer   region_info.SetReadable(MemoryRegionInfo::eNo);
709ad007563SHoward Hellyer   region_info.SetWritable(MemoryRegionInfo::eNo);
710ad007563SHoward Hellyer   region_info.SetExecutable(MemoryRegionInfo::eNo);
711ad007563SHoward Hellyer   region_info.SetMapped(MemoryRegionInfo::eNo);
71297206d57SZachary Turner   return Status();
7133385fa08SGreg Clayton }
7143385fa08SGreg Clayton 
Clear()715b9c1b51eSKate Stone void ProcessMachCore::Clear() { m_thread_list.Clear(); }
716c3776bf2SGreg Clayton 
Initialize()717b9c1b51eSKate Stone void ProcessMachCore::Initialize() {
718c5f28e2aSKamil Rytarowski   static llvm::once_flag g_once_flag;
719c3776bf2SGreg Clayton 
720c5f28e2aSKamil Rytarowski   llvm::call_once(g_once_flag, []() {
721c3776bf2SGreg Clayton     PluginManager::RegisterPlugin(GetPluginNameStatic(),
722b9c1b51eSKate Stone                                   GetPluginDescriptionStatic(), CreateInstance);
723c8d69828SDavide Italiano   });
724c3776bf2SGreg Clayton }
725c3776bf2SGreg Clayton 
GetImageInfoAddress()726b9c1b51eSKate Stone addr_t ProcessMachCore::GetImageInfoAddress() {
72705097246SAdrian Prantl   // If we found both a user-process dyld and a kernel binary, we need to
72805097246SAdrian Prantl   // decide which to prefer.
729b9c1b51eSKate Stone   if (GetCorefilePreference() == eKernelCorefile) {
730b9c1b51eSKate Stone     if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
7317e50d913SJason Molenda       return m_mach_kernel_addr;
732c3776bf2SGreg Clayton     }
733703a4561SJason Molenda     return m_dyld_addr;
734b9c1b51eSKate Stone   } else {
735b9c1b51eSKate Stone     if (m_dyld_addr != LLDB_INVALID_ADDRESS) {
736703a4561SJason Molenda       return m_dyld_addr;
737703a4561SJason Molenda     }
738703a4561SJason Molenda     return m_mach_kernel_addr;
739703a4561SJason Molenda   }
740703a4561SJason Molenda }
741c3776bf2SGreg Clayton 
GetCoreObjectFile()742b9c1b51eSKate Stone lldb_private::ObjectFile *ProcessMachCore::GetCoreObjectFile() {
7431f746071SGreg Clayton   return m_core_module_sp->GetObjectFile();
7441f746071SGreg Clayton }
745