29#include "llvm/Support/MathExtras.h"
52 return "Mach-O core file debugging plug-in.";
64 if (crash_file && !can_connect) {
65 const size_t header_size =
sizeof(llvm::MachO::mach_header);
67 crash_file->
GetPath(), header_size, 0);
68 if (data_sp && data_sp->GetByteSize() == header_size) {
73 llvm::MachO::mach_header mach_header;
76 if (mach_header.filetype == llvm::MachO::MH_CORE)
77 process_sp = std::make_shared<ProcessMachCore>(target_sp, listener_sp,
86 bool plugin_specified_by_name) {
87 if (plugin_specified_by_name)
134 llvm::MachO::mach_header header;
139 if (header.magic == llvm::MachO::MH_CIGAM ||
140 header.magic == llvm::MachO::MH_CIGAM_64) {
141 header.magic = llvm::byteswap<uint32_t>(header.magic);
142 header.cputype = llvm::byteswap<uint32_t>(header.cputype);
143 header.cpusubtype = llvm::byteswap<uint32_t>(header.cpusubtype);
144 header.filetype = llvm::byteswap<uint32_t>(header.filetype);
145 header.ncmds = llvm::byteswap<uint32_t>(header.ncmds);
146 header.sizeofcmds = llvm::byteswap<uint32_t>(header.sizeofcmds);
147 header.flags = llvm::byteswap<uint32_t>(header.flags);
150 if (header.magic == llvm::MachO::MH_MAGIC ||
151 header.magic == llvm::MachO::MH_MAGIC_64) {
156 switch (header.filetype) {
157 case llvm::MachO::MH_DYLINKER:
159 "ProcessMachCore::%s found a user "
160 "process dyld binary image at 0x%" PRIx64,
165 case llvm::MachO::MH_EXECUTE:
168 if ((header.flags & llvm::MachO::MH_DYLDLINK) == 0) {
170 "ProcessMachCore::%s found a mach "
171 "kernel binary image at 0x%" PRIx64,
188 bool ranges_are_sorted =
true;
190 for (uint32_t i = 0; i < num_sections; ++i) {
196 section_vm_addr, section->
GetByteSize(), file_range);
198 if (vm_addr > section_vm_addr)
199 ranges_are_sorted =
false;
205 last_entry->
data.GetRangeEnd() == range_entry.
data.GetRangeBase()) {
207 last_entry->
data.SetRangeEnd(range_entry.
data.GetRangeEnd());
216 if (permissions == 0)
217 permissions = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;
219 section_vm_addr, section->
GetByteSize(), permissions));
222 if (!ranges_are_sorted) {
237 uint64_t lowmem_uuid_addresses[] = {0x2000204, 0x1000204, 0x1000020, 0x4204,
238 0x1204, 0x1020, 0x4020, 0xc00,
241 for (uint64_t addr : lowmem_uuid_addresses) {
244 if (core_memory_entry) {
248 if (bytes_left >= 32) {
251 core_memory_entry->
data.GetRangeBase() + offset, 4, &strbuf) &&
252 strncmp(
"uuid", (
char *)&strbuf, 4) == 0) {
254 if (core_objfile->
CopyData(core_memory_entry->
data.GetRangeBase() +
256 sizeof(
uuid_t), uuid_bytes)) {
260 "ProcessMachCore::LoadBinaryViaLowmemUUID: found "
261 "binary uuid %s at low memory address 0x%" PRIx64,
266 bin_spec.
uuid = uuid;
273 llvm::Expected<ModuleSP> module =
279 << llvm::toString(module.takeError()) <<
"\n";
296 addr_t objfile_binary_value;
297 bool objfile_binary_value_is_offset;
298 UUID objfile_binary_uuid;
304 bool found_binary_spec_in_metadata =
false;
307 objfile_binary_value_is_offset,
308 objfile_binary_uuid, type)) {
310 log->
Printf(
"ProcessMachCore::LoadBinariesViaMetadata: using binary hint "
311 "from 'main bin spec' "
312 "LC_NOTE with UUID %s value 0x%" PRIx64
313 " value is offset %d and type %d",
315 objfile_binary_value, objfile_binary_value_is_offset, type);
317 found_binary_spec_in_metadata =
true;
333 bin_spec.
uuid = objfile_binary_uuid;
334 bin_spec.
value = objfile_binary_value;
340 llvm::Expected<ModuleSP> module =
346 << llvm::toString(module.takeError()) <<
"\n";
358 if (corefile_identifier.find(
"UUID=") != std::string::npos) {
359 size_t p = corefile_identifier.find(
"UUID=") + strlen(
"UUID=");
360 std::string uuid_str = corefile_identifier.substr(p, 36);
363 log->
Printf(
"Got a UUID from LC_IDENT/kern ver str LC_NOTE: %s",
365 found_binary_spec_in_metadata =
true;
367 if (corefile_identifier.find(
"stext=") != std::string::npos) {
368 size_t p = corefile_identifier.find(
"stext=") + strlen(
"stext=");
369 if (corefile_identifier[p] ==
'0' && corefile_identifier[p + 1] ==
'x') {
371 ::strtoul(corefile_identifier.c_str() + p,
nullptr, 16);
373 log->
Printf(
"Got a load address from LC_IDENT/kern ver str "
374 "LC_NOTE: 0x%" PRIx64,
376 found_binary_spec_in_metadata =
true;
382 if (corefile_identifier.find(
"Darwin Kernel") != std::string::npos &&
386 "ProcessMachCore::LoadBinariesViaMetadata: Found kernel binary via "
387 "LC_IDENT/kern ver str LC_NOTE");
389 found_binary_spec_in_metadata =
true;
390 }
else if (ident_uuid.
IsValid()) {
394 bin_spec.
uuid = ident_uuid;
395 bin_spec.
value = ident_binary_addr;
400 llvm::Expected<ModuleSP> module =
403 found_binary_spec_in_metadata =
true;
407 << llvm::toString(module.takeError()) <<
"\n";
414 found_binary_spec_in_metadata =
true;
419 found_binary_spec_in_metadata =
true;
428 return found_binary_spec_in_metadata;
438 std::vector<addr_t> dylds_found;
439 std::vector<addr_t> kernels_found;
450 "ProcessMachCore::%s: Setting target ArchSpec based on "
451 "corefile mach-o cputype/cpusubtype",
458 for (
size_t i = 0; i < num_core_aranges; ++i) {
462 for (
lldb::addr_t section_vm_addr = section_vm_addr_start;
463 section_vm_addr < section_vm_addr_end; section_vm_addr += 0x1000) {
467 dylds_found.push_back(dyld);
469 kernels_found.push_back(kernel);
476 if (dylds_found.size() > 0)
478 if (kernels_found.size() > 0)
482 if (kernels_found.size() < 2)
503 addr_t better_kernel_address =
511 "ProcessMachCore::%s: Using "
512 "the kernel address "
513 "from DynamicLoaderDarwinKernel",
523 if (!found_binary_spec_in_metadata)
532 "ProcessMachCore::%s: Using kernel "
539 "ProcessMachCore::%s: Using user process dyld "
540 "image at 0x%" PRIx64,
545 "ProcessMachCore::%s: Using user process dyld "
546 "dyld_all_image_infos at 0x%" PRIx64,
553 "ProcessMachCore::%s: Using user process dyld "
554 "image at 0x%" PRIx64,
559 "ProcessMachCore::%s: Using user process dyld "
560 "dyld_all_image_infos at 0x%" PRIx64,
564 "ProcessMachCore::%s: Using kernel "
585 for (
size_t i = 0; i < core_range_infos_size; i++) {
588 ent->
data = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;
603 if (core_objfile ==
nullptr) {
619 if (exe_module_sp && exe_module_sp->GetArchitecture().IsValid()) {
621 "ProcessMachCore::%s: Was given binary + corefile, setting "
622 "target ArchSpec to binary to start",
634 if (exe_module_sp && exe_module_sp->GetArchitecture().IsValid()) {
636 "ProcessMachCore::%s: have executable binary in the Target "
637 "after metadata/scan. Setting Target's ArchSpec based on "
646 "ProcessMachCore::%s: Setting target ArchSpec based on "
647 "corefile mach-o cputype/cpusubtype",
667 if (old_thread_list.
GetSize(
false) == 0) {
674 std::vector<lldb::tid_t> tids;
676 assert(tids.size() == num_threads);
680 for (uint32_t i = 0; i < num_threads; i++) {
682 highest_tid = tids[i];
685 for (uint32_t i = 0; i < num_threads; i++) {
687 tids[i] = current_unused_tid++;
692 for (uint32_t i = 0; i < num_threads; i++) {
697 for (uint32_t i = 0; i < num_threads; i++) {
699 std::make_shared<ThreadMachCore>(*
this, tids[i], i);
704 const uint32_t num_threads = old_thread_list.
GetSize(
false);
705 for (uint32_t i = 0; i < num_threads; ++i)
708 return new_thread_list.
GetSize(
false) > 0;
739 size_t bytes_read = 0;
758 while (bytes_read < size) {
759 const addr_t curr_addr = addr + bytes_read;
763 if (core_memory_entry) {
766 const size_t bytes_to_read =
767 std::min(size - bytes_read, (
size_t)bytes_left);
768 const size_t curr_bytes_read = core_objfile->
CopyData(
769 core_memory_entry->
data.GetRangeBase() + offset, bytes_to_read,
770 (
char *)buf + bytes_read);
771 if (curr_bytes_read == 0)
773 bytes_read += curr_bytes_read;
778 "core file does not contain 0x%" PRIx64, curr_addr);
792 if (permission_entry) {
793 if (permission_entry->
Contains(load_addr)) {
796 const Flags permissions(permission_entry->
data);
805 }
else if (load_addr < permission_entry->GetRangeBase()) {
823 section_sp->GetLoadBaseAddress(&
GetTarget()));
static llvm::raw_ostream & error(Stream &strm)
static llvm::Expected< lldb::addr_t > ResolveLoadAddress(EvalContext &eval_ctx, const char *dw_op_type, lldb::addr_t file_addr, Address &so_addr, bool check_sectionoffset=false)
Helper function to move common code used to resolve a file address and turn into a load address.
#define LLDB_LOGF(log,...)
#define LLDB_PLUGIN_DEFINE(PluginName)
static llvm::StringRef GetPluginNameStatic()
static lldb::addr_t SearchForDarwinKernel(lldb_private::Process *process)
static llvm::StringRef GetPluginNameStatic()
static llvm::StringRef GetPluginNameStatic()
bool ParseHeader() override
Attempts to parse the object header.
bool WarnBeforeDetach() const override
Before lldb detaches from a process, it warns the user that they are about to lose their debug sessio...
static llvm::StringRef GetPluginDescriptionStatic()
size_t DoReadMemory(const lldb_private::ProcessAddress &addr, void *buf, size_t size, lldb_private::Status &error) override
Actually do the reading of memory from a process.
bool LoadBinaryViaLowmemUUID()
VMRangeToFileOffset m_core_aranges
bool LoadBinariesViaMetadata()
CorefilePreference GetCorefilePreference()
If a core file can be interpreted multiple ways, this establishes which style wins.
bool CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override
Check if a plug-in instance can debug the file in module.
void CleanupMemoryRegionPermissions()
lldb_private::ObjectFile * GetCoreObjectFile()
ProcessMachCore(lldb::TargetSP target_sp, lldb::ListenerSP listener, const lldb_private::FileSpec &core_file)
llvm::StringRef m_dyld_plugin_name
lldb_private::DynamicLoader * GetDynamicLoader() override
Get the dynamic loader plug-in for this process.
lldb_private::Status DoDestroy() override
static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener, const lldb_private::FileSpec *crash_file_path, bool can_connect)
lldb::addr_t m_dyld_all_image_infos_addr
void RefreshStateAfterStop() override
Currently called as part of ShouldStop.
bool DoUpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list) override
Update the thread list following process plug-in's specific logic.
static llvm::StringRef GetPluginNameStatic()
bool IsAlive() override
Check if a process is still alive.
void CreateMemoryRegions()
size_t ReadMemory(const lldb_private::ProcessAddress &addr, void *buf, size_t size, lldb_private::Status &error) override
Read of memory from a process.
bool CheckAddressForDyldOrKernel(lldb::addr_t addr, lldb::addr_t &dyld, lldb::addr_t &kernel)
lldb_private::Range< lldb::addr_t, lldb::addr_t > FileRange
VMRangeToPermissions m_core_range_infos
lldb_private::Status DoLoadCore() override
void LoadBinariesViaExhaustiveSearch()
void LoadBinariesAndSetDYLD()
lldb::addr_t m_mach_kernel_addr
lldb::addr_t GetImageInfoAddress() override
Get the image information address for the current process.
~ProcessMachCore() override
lldb::ModuleSP m_core_module_sp
lldb_private::Status DoGetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo ®ion_info) override
DoGetMemoryRegionInfo is called by GetMemoryRegionInfo after it has removed non address bits from loa...
A section + offset based address class.
lldb::SectionSP GetSection() const
Get const accessor for the section.
A class which holds the metadata from a remote stub/corefile note about how many bits are used for ad...
An architecture specification class.
bool IsValid() const
Tests if this ArchSpec is valid.
lldb::StreamUP GetAsyncErrorStream()
A plug-in interface definition class for dynamic loaders.
static llvm::Expected< lldb::ModuleSP > LocateAndLoadBinary(Process *process, BinarySpec &bin_spec)
Find a binary and load it into a Target.
static DynamicLoader * FindPlugin(Process *process, llvm::StringRef plugin_name)
Find a dynamic loader plugin for a given process.
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
static FileSystem & Instance()
std::shared_ptr< DataBuffer > CreateDataBuffer(const llvm::Twine &path, uint64_t size=0, uint64_t offset=0)
Create memory buffer from path.
bool Test(ValueType bit) const
Test a single flag bit.
void void Printf(const char *format,...) __attribute__((format(printf
Prefer using LLDB_LOGF whenever possible.
void SetReadable(LazyBool val)
void SetLLDBPermissions(uint32_t permissions)
void SetMapped(LazyBool val)
void SetExecutable(LazyBool val)
void SetWritable(LazyBool val)
static Status GetSharedModule(const ModuleSpec &module_spec, lldb::ModuleSP &module_sp, llvm::SmallVectorImpl< lldb::ModuleSP > *old_modules, bool *did_create_ptr, bool invoke_locate_callback=true, bool invoke_symbol_locators=true)
void SetTarget(lldb::TargetSP target)
Set the target to be used when resolving a module.
A plug-in interface definition class for object file parsers.
virtual bool GetCorefileThreadExtraInfos(std::vector< lldb::tid_t > &tids)
Get metadata about thread ids from the corefile.
virtual std::string GetIdentifierString()
Some object files may have an identifier string embedded in them, e.g.
virtual uint32_t GetNumThreadContexts()
virtual bool LoadCoreFileImages(lldb_private::Process &process)
Load binaries listed in a corefile.
@ eTypeCoreFile
A core file that has a checkpoint of a program's execution state.
virtual lldb_private::AddressableBits GetAddressableBits()
Some object files may have the number of bits used for addressing embedded in them,...
size_t CopyData(lldb::offset_t offset, size_t length, void *dst) const
virtual SectionList * GetSectionList(bool update_module_section_list=true)
Gets the section list for the currently selected architecture (and object for archives).
virtual bool GetCorefileMainBinaryInfo(lldb::addr_t &value, bool &value_is_offset, UUID &uuid, ObjectFile::BinaryType &type)
When the ObjectFile is a core file, lldb needs to locate the "binary" in the core file.
BinaryType
If we have a corefile binary hint, this enum specifies the binary type which we can use to select the...
@ eBinaryTypeKernel
kernel binary
@ eBinaryTypeUser
user process binary, dyld addr
@ eBinaryTypeUserAllImageInfos
user process binary, dyld_all_image_infos addr
virtual llvm::StringRef GetPluginName()=0
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
PostMortemProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec &core_file)
An address in a process, qualified by an address space.
lldb::addr_t GetValue() const
void SetAddressableBitMasks(AddressableBits bit_masks)
void SetCanJIT(bool can_jit)
Sets whether executing JIT-compiled code in this process is possible.
lldb::DynamicLoaderUP m_dyld_up
lldb::addr_t FixAnyAddress(lldb::addr_t pc)
Use this method when you do not know, or do not care what kind of address you are fixing.
bool IsValid() const
Return whether this object is valid (i.e.
virtual void Finalize(bool destructing)
This object is about to be destroyed, do any necessary cleanup.
ThreadList m_thread_list
The threads for this process as the user will see them.
Target & GetTarget()
Get the target object pointer for this module.
RangeData< lldb::addr_t, lldb::addr_t, FileRange > Entry
size_t GetNumSections(uint32_t depth) const
lldb::SectionSP GetSectionAtIndex(size_t idx) const
uint32_t GetPermissions() const
Get the permissions as OR'ed bits from lldb::Permissions.
lldb::offset_t GetFileOffset() const
lldb::addr_t GetFileAddress() const
lldb::addr_t GetByteSize() const
lldb::offset_t GetFileSize() const
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
static Status FromErrorString(const char *str)
Debugger & GetDebugger() const
bool SetArchitecture(const ArchSpec &arch_spec, bool set_platform=false, bool merge=true)
Set the architecture for this target.
lldb::ModuleSP GetExecutableModule()
Gets the module for the main executable.
void AddThread(const lldb::ThreadSP &thread_sp)
uint32_t GetSize(bool can_update=true)
lldb::ThreadSP GetThreadAtIndex(uint32_t idx, bool can_update=true)
Represents UUID's of various sizes.
bool SetFromStringRef(llvm::StringRef str)
std::string GetAsString(llvm::StringRef separator="-") const
#define LLDB_INVALID_THREAD_ID
#define LLDB_INVALID_ADDRESS
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
std::shared_ptr< lldb_private::Thread > ThreadSP
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::Listener > ListenerSP
std::shared_ptr< lldb_private::Section > SectionSP
std::shared_ptr< lldb_private::Target > TargetSP
std::shared_ptr< lldb_private::DataExtractor > DataExtractorSP
std::shared_ptr< lldb_private::Module > ModuleSP
A binary to find and load into a Target.
lldb::addr_t value
Address where the binary should be loaded, or read out of memory.
UUID uuid
UUID of the binary to be loaded.
bool is_main_executable
Whether this is the process' main executable.
bool force_symbol_search
Allow the search to do a possibly expensive external search for the ObjectFile and/or SymbolFile.
bool set_address_in_target
Whether the address of the binary should be set in the Target if it is added.
bool notify
Whether ModulesDidLoad should be called once the binary has been added to the Target.
bool value_is_offset
A flag indicating that value is an address, or an offset to be applied to the file addresses.
bool Contains(BaseType r) const
BaseType GetRangeBase() const
void SetRangeEnd(BaseType end)
void SetRangeBase(BaseType b)
Set the start value for the range, and keep the same size.
BaseType GetRangeEnd() const
void SetByteSize(SizeType s)