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 ®ion_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