brintos

brintos / llvm-project-archived public Read only

0
0
Text · 35.1 KiB · 83d684e Raw
874 lines · cpp
1//===-- ProcessMachCore.cpp -----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include <cerrno>10#include <cstdlib>11 12#include "llvm/Support/MathExtras.h"13#include "llvm/Support/Threading.h"14 15#include "lldb/Core/Debugger.h"16#include "lldb/Core/Module.h"17#include "lldb/Core/ModuleSpec.h"18#include "lldb/Core/PluginManager.h"19#include "lldb/Core/Section.h"20#include "lldb/Host/Host.h"21#include "lldb/Symbol/ObjectFile.h"22#include "lldb/Target/MemoryRegionInfo.h"23#include "lldb/Target/SectionLoadList.h"24#include "lldb/Target/Target.h"25#include "lldb/Target/Thread.h"26#include "lldb/Utility/AppleUuidCompatibility.h"27#include "lldb/Utility/DataBuffer.h"28#include "lldb/Utility/LLDBLog.h"29#include "lldb/Utility/Log.h"30#include "lldb/Utility/State.h"31#include "lldb/Utility/UUID.h"32 33#include "ProcessMachCore.h"34#include "Plugins/Process/Utility/StopInfoMachException.h"35#include "ThreadMachCore.h"36 37// Needed for the plug-in names for the dynamic loaders.38#include "lldb/Host/SafeMachO.h"39 40#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"41#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h"42#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"43#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"44#include "Plugins/Platform/MacOSX/PlatformDarwinKernel.h"45 46#include <memory>47#include <mutex>48 49using namespace lldb;50using namespace lldb_private;51 52LLDB_PLUGIN_DEFINE(ProcessMachCore)53 54llvm::StringRef ProcessMachCore::GetPluginDescriptionStatic() {55  return "Mach-O core file debugging plug-in.";56}57 58void ProcessMachCore::Terminate() {59  PluginManager::UnregisterPlugin(ProcessMachCore::CreateInstance);60}61 62lldb::ProcessSP ProcessMachCore::CreateInstance(lldb::TargetSP target_sp,63                                                ListenerSP listener_sp,64                                                const FileSpec *crash_file,65                                                bool can_connect) {66  lldb::ProcessSP process_sp;67  if (crash_file && !can_connect) {68    const size_t header_size = sizeof(llvm::MachO::mach_header);69    auto data_sp = FileSystem::Instance().CreateDataBuffer(70        crash_file->GetPath(), header_size, 0);71    if (data_sp && data_sp->GetByteSize() == header_size) {72      DataExtractor data(data_sp, lldb::eByteOrderLittle, 4);73 74      lldb::offset_t data_offset = 0;75      llvm::MachO::mach_header mach_header;76      if (ObjectFileMachO::ParseHeader(data, &data_offset, mach_header)) {77        if (mach_header.filetype == llvm::MachO::MH_CORE)78          process_sp = std::make_shared<ProcessMachCore>(target_sp, listener_sp,79                                                         *crash_file);80      }81    }82  }83  return process_sp;84}85 86bool ProcessMachCore::CanDebug(lldb::TargetSP target_sp,87                               bool plugin_specified_by_name) {88  if (plugin_specified_by_name)89    return true;90 91  // For now we are just making sure the file exists for a given module92  if (!m_core_module_sp && FileSystem::Instance().Exists(m_core_file)) {93    // Don't add the Target's architecture to the ModuleSpec - we may be94    // working with a core file that doesn't have the correct cpusubtype in the95    // header but we should still try to use it -96    // ModuleSpecList::FindMatchingModuleSpec enforces a strict arch mach.97    ModuleSpec core_module_spec(m_core_file);98    core_module_spec.SetTarget(target_sp);99    Status error(ModuleList::GetSharedModule(core_module_spec, m_core_module_sp,100                                             nullptr, nullptr));101 102    if (m_core_module_sp) {103      ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();104      if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile)105        return true;106    }107  }108  return false;109}110 111// ProcessMachCore constructor112ProcessMachCore::ProcessMachCore(lldb::TargetSP target_sp,113                                 ListenerSP listener_sp,114                                 const FileSpec &core_file)115    : PostMortemProcess(target_sp, listener_sp, core_file), m_core_aranges(),116      m_core_range_infos(), m_core_module_sp(),117      m_dyld_addr(LLDB_INVALID_ADDRESS),118      m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS),119      m_mach_kernel_addr(LLDB_INVALID_ADDRESS) {}120 121// Destructor122ProcessMachCore::~ProcessMachCore() {123  Clear();124  // We need to call finalize on the process before destroying ourselves to125  // make sure all of the broadcaster cleanup goes as planned. If we destruct126  // this class, then Process::~Process() might have problems trying to fully127  // destroy the broadcaster.128  Finalize(true /* destructing */);129}130 131bool ProcessMachCore::CheckAddressForDyldOrKernel(lldb::addr_t addr,132                                                  addr_t &dyld,133                                                  addr_t &kernel) {134  Log *log(GetLog(LLDBLog::DynamicLoader | LLDBLog::Process));135  llvm::MachO::mach_header header;136  Status error;137  dyld = kernel = LLDB_INVALID_ADDRESS;138  if (DoReadMemory(addr, &header, sizeof(header), error) != sizeof(header))139    return false;140  if (header.magic == llvm::MachO::MH_CIGAM ||141      header.magic == llvm::MachO::MH_CIGAM_64) {142    header.magic = llvm::byteswap<uint32_t>(header.magic);143    header.cputype = llvm::byteswap<uint32_t>(header.cputype);144    header.cpusubtype = llvm::byteswap<uint32_t>(header.cpusubtype);145    header.filetype = llvm::byteswap<uint32_t>(header.filetype);146    header.ncmds = llvm::byteswap<uint32_t>(header.ncmds);147    header.sizeofcmds = llvm::byteswap<uint32_t>(header.sizeofcmds);148    header.flags = llvm::byteswap<uint32_t>(header.flags);149  }150 151  if (header.magic == llvm::MachO::MH_MAGIC ||152      header.magic == llvm::MachO::MH_MAGIC_64) {153    // Check MH_EXECUTABLE to see if we can find the mach image that contains154    // the shared library list. The dynamic loader (dyld) is what contains the155    // list for user applications, and the mach kernel contains a global that156    // has the list of kexts to load157    switch (header.filetype) {158    case llvm::MachO::MH_DYLINKER:159      LLDB_LOGF(log,160                "ProcessMachCore::%s found a user "161                "process dyld binary image at 0x%" PRIx64,162                __FUNCTION__, addr);163      dyld = addr;164      return true;165 166    case llvm::MachO::MH_EXECUTE:167      // Check MH_EXECUTABLE file types to see if the dynamic link object flag168      // is NOT set. If it isn't, then we have a mach_kernel.169      if ((header.flags & llvm::MachO::MH_DYLDLINK) == 0) {170        LLDB_LOGF(log,171                  "ProcessMachCore::%s found a mach "172                  "kernel binary image at 0x%" PRIx64,173                  __FUNCTION__, addr);174        // Address of the mach kernel "struct mach_header" in the core file.175        kernel = addr;176        return true;177      }178      break;179    }180  }181  return false;182}183 184void ProcessMachCore::CreateMemoryRegions() {185  ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();186  SectionList *section_list = core_objfile->GetSectionList();187  const uint32_t num_sections = section_list->GetNumSections(0);188 189  bool ranges_are_sorted = true;190  addr_t vm_addr = 0;191  for (uint32_t i = 0; i < num_sections; ++i) {192    Section *section = section_list->GetSectionAtIndex(i).get();193    if (section && section->GetFileSize() > 0) {194      lldb::addr_t section_vm_addr = section->GetFileAddress();195      FileRange file_range(section->GetFileOffset(), section->GetFileSize());196      VMRangeToFileOffset::Entry range_entry(197          section_vm_addr, section->GetByteSize(), file_range);198 199      if (vm_addr > section_vm_addr)200        ranges_are_sorted = false;201      vm_addr = section->GetFileAddress();202      VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();203 204      if (last_entry &&205          last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&206          last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase()) {207        last_entry->SetRangeEnd(range_entry.GetRangeEnd());208        last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd());209      } else {210        m_core_aranges.Append(range_entry);211      }212      // Some core files don't fill in the permissions correctly. If that is213      // the case assume read + execute so clients don't think the memory is214      // not readable, or executable. The memory isn't writable since this215      // plug-in doesn't implement DoWriteMemory.216      uint32_t permissions = section->GetPermissions();217      if (permissions == 0)218        permissions = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;219      m_core_range_infos.Append(VMRangeToPermissions::Entry(220          section_vm_addr, section->GetByteSize(), permissions));221    }222  }223  if (!ranges_are_sorted) {224    m_core_aranges.Sort();225    m_core_range_infos.Sort();226  }227}228 229// Some corefiles have a UUID stored in a low memory230// address.  We inspect a set list of addresses for231// the characters 'uuid' and 16 bytes later there will232// be a uuid_t UUID.  If we can find a binary that233// matches the UUID, it is loaded with no slide in the target.234bool ProcessMachCore::LoadBinaryViaLowmemUUID() {235  Log *log(GetLog(LLDBLog::DynamicLoader | LLDBLog::Process));236  ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();237 238  uint64_t lowmem_uuid_addresses[] = {0x2000204, 0x1000204, 0x1000020, 0x4204,239                                      0x1204,    0x1020,    0x4020,    0xc00,240                                      0xC0,      0};241 242  for (uint64_t addr : lowmem_uuid_addresses) {243    const VMRangeToFileOffset::Entry *core_memory_entry =244        m_core_aranges.FindEntryThatContains(addr);245    if (core_memory_entry) {246      const addr_t offset = addr - core_memory_entry->GetRangeBase();247      const addr_t bytes_left = core_memory_entry->GetRangeEnd() - addr;248      // (4-bytes 'uuid' + 12 bytes pad for align + 16 bytes uuid_t) == 32 bytes249      if (bytes_left >= 32) {250        char strbuf[4];251        if (core_objfile->CopyData(252                core_memory_entry->data.GetRangeBase() + offset, 4, &strbuf) &&253            strncmp("uuid", (char *)&strbuf, 4) == 0) {254          uuid_t uuid_bytes;255          if (core_objfile->CopyData(core_memory_entry->data.GetRangeBase() +256                                         offset + 16,257                                     sizeof(uuid_t), uuid_bytes)) {258            UUID uuid(uuid_bytes, sizeof(uuid_t));259            if (uuid.IsValid()) {260              LLDB_LOGF(log,261                        "ProcessMachCore::LoadBinaryViaLowmemUUID: found "262                        "binary uuid %s at low memory address 0x%" PRIx64,263                        uuid.GetAsString().c_str(), addr);264              // We have no address specified, only a UUID.  Load it at the file265              // address.266              const bool value_is_offset = true;267              const bool force_symbol_search = true;268              const bool notify = true;269              const bool set_address_in_target = true;270              const bool allow_memory_image_last_resort = false;271              if (DynamicLoader::LoadBinaryWithUUIDAndAddress(272                      this, llvm::StringRef(), uuid, 0, value_is_offset,273                      force_symbol_search, notify, set_address_in_target,274                      allow_memory_image_last_resort)) {275                m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic();276              }277              // We found metadata saying which binary should be loaded; don't278              // try an exhaustive search.279              return true;280            }281          }282        }283      }284    }285  }286  return false;287}288 289bool ProcessMachCore::LoadBinariesViaMetadata() {290  Log *log(GetLog(LLDBLog::DynamicLoader | LLDBLog::Process));291  ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();292 293  addr_t objfile_binary_value;294  bool objfile_binary_value_is_offset;295  UUID objfile_binary_uuid;296  ObjectFile::BinaryType type;297 298  // This will be set to true if we had a metadata hint299  // specifying a UUID or address -- and we should not fall back300  // to doing an exhaustive search.301  bool found_binary_spec_in_metadata = false;302 303  if (core_objfile->GetCorefileMainBinaryInfo(objfile_binary_value,304                                              objfile_binary_value_is_offset,305                                              objfile_binary_uuid, type)) {306    if (log) {307      log->Printf("ProcessMachCore::LoadBinariesViaMetadata: using binary hint "308                  "from 'main bin spec' "309                  "LC_NOTE with UUID %s value 0x%" PRIx64310                  " value is offset %d and type %d",311                  objfile_binary_uuid.GetAsString().c_str(),312                  objfile_binary_value, objfile_binary_value_is_offset, type);313    }314    found_binary_spec_in_metadata = true;315 316    // If this is the xnu kernel, don't load it now.  Note the correct317    // DynamicLoader plugin to use, and the address of the kernel, and318    // let the DynamicLoader handle the finding & loading of the binary.319    if (type == ObjectFile::eBinaryTypeKernel) {320      m_mach_kernel_addr = objfile_binary_value;321      m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();322    } else if (type == ObjectFile::eBinaryTypeUser) {323      m_dyld_addr = objfile_binary_value;324      m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();325    } else if (type == ObjectFile::eBinaryTypeUserAllImageInfos) {326      m_dyld_all_image_infos_addr = objfile_binary_value;327      m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();328    } else {329      const bool force_symbol_search = true;330      const bool notify = true;331      const bool set_address_in_target = true;332      const bool allow_memory_image_last_resort = false;333      if (DynamicLoader::LoadBinaryWithUUIDAndAddress(334              this, llvm::StringRef(), objfile_binary_uuid,335              objfile_binary_value, objfile_binary_value_is_offset,336              force_symbol_search, notify, set_address_in_target,337              allow_memory_image_last_resort)) {338        m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic();339      }340    }341  }342 343  // This checks for the presence of an LC_IDENT string in a core file;344  // LC_IDENT is very obsolete and should not be used in new code, but if the345  // load command is present, let's use the contents.346  UUID ident_uuid;347  addr_t ident_binary_addr = LLDB_INVALID_ADDRESS;348    std::string corefile_identifier = core_objfile->GetIdentifierString();349 350    // Search for UUID= and stext= strings in the identifier str.351    if (corefile_identifier.find("UUID=") != std::string::npos) {352      size_t p = corefile_identifier.find("UUID=") + strlen("UUID=");353      std::string uuid_str = corefile_identifier.substr(p, 36);354      ident_uuid.SetFromStringRef(uuid_str);355      if (log)356        log->Printf("Got a UUID from LC_IDENT/kern ver str LC_NOTE: %s",357                    ident_uuid.GetAsString().c_str());358      found_binary_spec_in_metadata = true;359    }360    if (corefile_identifier.find("stext=") != std::string::npos) {361      size_t p = corefile_identifier.find("stext=") + strlen("stext=");362      if (corefile_identifier[p] == '0' && corefile_identifier[p + 1] == 'x') {363        ident_binary_addr =364            ::strtoul(corefile_identifier.c_str() + p, nullptr, 16);365        if (log)366          log->Printf("Got a load address from LC_IDENT/kern ver str "367                      "LC_NOTE: 0x%" PRIx64,368                      ident_binary_addr);369        found_binary_spec_in_metadata = true;370      }371    }372 373    // Search for a "Darwin Kernel" str indicating kernel; else treat as374    // standalone375    if (corefile_identifier.find("Darwin Kernel") != std::string::npos &&376        ident_uuid.IsValid() && ident_binary_addr != LLDB_INVALID_ADDRESS) {377      if (log)378        log->Printf(379            "ProcessMachCore::LoadBinariesViaMetadata: Found kernel binary via "380            "LC_IDENT/kern ver str LC_NOTE");381      m_mach_kernel_addr = ident_binary_addr;382      found_binary_spec_in_metadata = true;383    } else if (ident_uuid.IsValid()) {384      // We have no address specified, only a UUID.  Load it at the file385      // address.386      const bool value_is_offset = false;387      const bool force_symbol_search = true;388      const bool notify = true;389      const bool set_address_in_target = true;390      const bool allow_memory_image_last_resort = false;391      if (DynamicLoader::LoadBinaryWithUUIDAndAddress(392              this, llvm::StringRef(), ident_uuid, ident_binary_addr,393              value_is_offset, force_symbol_search, notify,394              set_address_in_target, allow_memory_image_last_resort)) {395        found_binary_spec_in_metadata = true;396        m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic();397      }398    }399 400  // Finally, load any binaries noted by "load binary" LC_NOTEs in the401  // corefile402  if (core_objfile->LoadCoreFileImages(*this)) {403    found_binary_spec_in_metadata = true;404    m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic();405  }406 407  if (!found_binary_spec_in_metadata && LoadBinaryViaLowmemUUID())408    found_binary_spec_in_metadata = true;409 410  // LoadCoreFileImges may have set the dynamic loader, e.g. in411  // PlatformDarwinKernel::LoadPlatformBinaryAndSetup().412  // If we now have a dynamic loader, save its name so we don't 413  // un-set it later.414  if (m_dyld_up)415    m_dyld_plugin_name = GetDynamicLoader()->GetPluginName();416 417  return found_binary_spec_in_metadata;418}419 420void ProcessMachCore::LoadBinariesViaExhaustiveSearch() {421  Log *log(GetLog(LLDBLog::DynamicLoader | LLDBLog::Process));422 423  // Search the pages of the corefile for dyld or mach kernel424  // binaries.  There may be multiple things that look like a kernel425  // in the corefile; disambiguating to the correct one can be difficult.426 427  std::vector<addr_t> dylds_found;428  std::vector<addr_t> kernels_found;429 430  // To do an exhaustive search, we'll need to create data extractors431  // to get correctly sized/endianness fields.  If we had a main binary432  // already, we would have set the Target to that - so here we'll use433  // the corefile's cputype/cpusubtype as the best guess.434  if (!GetTarget().GetArchitecture().IsValid()) {435    // The corefile's architecture is our best starting point.436    ArchSpec arch(m_core_module_sp->GetArchitecture());437    if (arch.IsValid()) {438      LLDB_LOGF(log,439                "ProcessMachCore::%s: Setting target ArchSpec based on "440                "corefile mach-o cputype/cpusubtype",441                __FUNCTION__);442      GetTarget().SetArchitecture(arch);443    }444  }445 446  const size_t num_core_aranges = m_core_aranges.GetSize();447  for (size_t i = 0; i < num_core_aranges; ++i) {448    const VMRangeToFileOffset::Entry *entry = m_core_aranges.GetEntryAtIndex(i);449    lldb::addr_t section_vm_addr_start = entry->GetRangeBase();450    lldb::addr_t section_vm_addr_end = entry->GetRangeEnd();451    for (lldb::addr_t section_vm_addr = section_vm_addr_start;452         section_vm_addr < section_vm_addr_end; section_vm_addr += 0x1000) {453      addr_t dyld, kernel;454      if (CheckAddressForDyldOrKernel(section_vm_addr, dyld, kernel)) {455        if (dyld != LLDB_INVALID_ADDRESS)456          dylds_found.push_back(dyld);457        if (kernel != LLDB_INVALID_ADDRESS)458          kernels_found.push_back(kernel);459      }460    }461  }462 463  // If we found more than one dyld mach-o header in the corefile,464  // pick the first one.465  if (dylds_found.size() > 0)466    m_dyld_addr = dylds_found[0];467  if (kernels_found.size() > 0)468    m_mach_kernel_addr = kernels_found[0];469 470  // Zero or one kernels found, we're done.471  if (kernels_found.size() < 2)472    return;473 474  // In the case of multiple kernel images found in the core file via475  // exhaustive search, we may not pick the correct one.  See if the476  // DynamicLoaderDarwinKernel's search heuristics might identify the correct477  // one.478 479  // SearchForDarwinKernel will call this class' GetImageInfoAddress method480  // which will give it the addresses we already have.481  // Save those aside and set482  // m_mach_kernel_addr/m_dyld_addr to an invalid address temporarily so483  // DynamicLoaderDarwinKernel does a real search for the kernel using its484  // own heuristics.485 486  addr_t saved_mach_kernel_addr = m_mach_kernel_addr;487  addr_t saved_user_dyld_addr = m_dyld_addr;488  m_mach_kernel_addr = LLDB_INVALID_ADDRESS;489  m_dyld_addr = LLDB_INVALID_ADDRESS;490  m_dyld_all_image_infos_addr = LLDB_INVALID_ADDRESS;491 492  addr_t better_kernel_address =493      DynamicLoaderDarwinKernel::SearchForDarwinKernel(this);494 495  m_mach_kernel_addr = saved_mach_kernel_addr;496  m_dyld_addr = saved_user_dyld_addr;497 498  if (better_kernel_address != LLDB_INVALID_ADDRESS) {499    LLDB_LOGF(log,500              "ProcessMachCore::%s: Using "501              "the kernel address "502              "from DynamicLoaderDarwinKernel",503              __FUNCTION__);504    m_mach_kernel_addr = better_kernel_address;505  }506}507 508void ProcessMachCore::LoadBinariesAndSetDYLD() {509  Log *log(GetLog(LLDBLog::DynamicLoader | LLDBLog::Process));510 511  bool found_binary_spec_in_metadata = LoadBinariesViaMetadata();512  if (!found_binary_spec_in_metadata)513    LoadBinariesViaExhaustiveSearch();514 515  if (m_dyld_plugin_name.empty()) {516    // If we found both a user-process dyld and a kernel binary, we need to517    // decide which to prefer.518    if (GetCorefilePreference() == eKernelCorefile) {519      if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {520        LLDB_LOGF(log,521                  "ProcessMachCore::%s: Using kernel "522                  "corefile image "523                  "at 0x%" PRIx64,524                  __FUNCTION__, m_mach_kernel_addr);525        m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();526      } else if (m_dyld_addr != LLDB_INVALID_ADDRESS) {527        LLDB_LOGF(log,528                  "ProcessMachCore::%s: Using user process dyld "529                  "image at 0x%" PRIx64,530                  __FUNCTION__, m_dyld_addr);531        m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();532      } else if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) {533        LLDB_LOGF(log,534                  "ProcessMachCore::%s: Using user process dyld "535                  "dyld_all_image_infos at 0x%" PRIx64,536                  __FUNCTION__, m_dyld_all_image_infos_addr);537        m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();538      }539    } else {540      if (m_dyld_addr != LLDB_INVALID_ADDRESS) {541        LLDB_LOGF(log,542                  "ProcessMachCore::%s: Using user process dyld "543                  "image at 0x%" PRIx64,544                  __FUNCTION__, m_dyld_addr);545        m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();546      } else if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) {547        LLDB_LOGF(log,548                  "ProcessMachCore::%s: Using user process dyld "549                  "dyld_all_image_infos at 0x%" PRIx64,550                  __FUNCTION__, m_dyld_all_image_infos_addr);551      } else if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {552        LLDB_LOGF(log,553                  "ProcessMachCore::%s: Using kernel "554                  "corefile image "555                  "at 0x%" PRIx64,556                  __FUNCTION__, m_mach_kernel_addr);557        m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();558      }559    }560  }561}562 563void ProcessMachCore::CleanupMemoryRegionPermissions() {564  if (m_dyld_plugin_name != DynamicLoaderMacOSXDYLD::GetPluginNameStatic()) {565    // For non-user process core files, the permissions on the core file566    // segments are usually meaningless, they may be just "read", because we're567    // dealing with kernel coredumps or early startup coredumps and the dumper568    // is grabbing pages of memory without knowing what they are.  If they569    // aren't marked as "executable", that can break the unwinder which will570    // check a pc value to see if it is in an executable segment and stop the571    // backtrace early if it is not ("executable" and "unknown" would both be572    // fine, but "not executable" will break the unwinder).573    size_t core_range_infos_size = m_core_range_infos.GetSize();574    for (size_t i = 0; i < core_range_infos_size; i++) {575      VMRangeToPermissions::Entry *ent =576          m_core_range_infos.GetMutableEntryAtIndex(i);577      ent->data = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;578    }579  }580}581 582// Process Control583Status ProcessMachCore::DoLoadCore() {584  Status error;585  if (!m_core_module_sp) {586    error = Status::FromErrorString("invalid core module");587    return error;588  }589  Log *log(GetLog(LLDBLog::DynamicLoader | LLDBLog::Target));590 591  ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();592  if (core_objfile == nullptr) {593    error = Status::FromErrorString("invalid core object file");594    return error;595  }596 597  SetCanJIT(false);598 599  // If we have an executable binary in the Target already,600  // use that to set the Target's ArchSpec.601  //602  // Don't initialize the ArchSpec based on the corefile's cputype/cpusubtype603  // here, the corefile creator may not know the correct subtype of the code604  // that is executing, initialize the Target to that, and if the605  // main binary has Python code which initializes based on the Target arch,606  // get the wrong subtype value.607  ModuleSP exe_module_sp = GetTarget().GetExecutableModule();608  if (exe_module_sp && exe_module_sp->GetArchitecture().IsValid()) {609    LLDB_LOGF(log,610              "ProcessMachCore::%s: Was given binary + corefile, setting "611              "target ArchSpec to binary to start",612              __FUNCTION__);613    GetTarget().SetArchitecture(exe_module_sp->GetArchitecture());614  }615 616  CreateMemoryRegions();617 618  LoadBinariesAndSetDYLD();619 620  CleanupMemoryRegionPermissions();621 622  exe_module_sp = GetTarget().GetExecutableModule();623  if (exe_module_sp && exe_module_sp->GetArchitecture().IsValid()) {624    LLDB_LOGF(log,625              "ProcessMachCore::%s: have executable binary in the Target "626              "after metadata/scan.  Setting Target's ArchSpec based on "627              "that.",628              __FUNCTION__);629    GetTarget().SetArchitecture(exe_module_sp->GetArchitecture());630  } else {631    // The corefile's architecture is our best starting point.632    ArchSpec arch(m_core_module_sp->GetArchitecture());633    if (arch.IsValid()) {634      LLDB_LOGF(log,635                "ProcessMachCore::%s: Setting target ArchSpec based on "636                "corefile mach-o cputype/cpusubtype",637                __FUNCTION__);638      GetTarget().SetArchitecture(arch);639    }640  }641 642  AddressableBits addressable_bits = core_objfile->GetAddressableBits();643  SetAddressableBitMasks(addressable_bits);644 645  return error;646}647 648lldb_private::DynamicLoader *ProcessMachCore::GetDynamicLoader() {649  if (m_dyld_up.get() == nullptr)650    m_dyld_up.reset(DynamicLoader::FindPlugin(this, m_dyld_plugin_name));651  return m_dyld_up.get();652}653 654bool ProcessMachCore::DoUpdateThreadList(ThreadList &old_thread_list,655                                         ThreadList &new_thread_list) {656  if (old_thread_list.GetSize(false) == 0) {657    // Make up the thread the first time this is called so we can setup our one658    // and only core thread state.659    ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();660 661    if (core_objfile) {662      const uint32_t num_threads = core_objfile->GetNumThreadContexts();663      std::vector<lldb::tid_t> tids;664      if (core_objfile->GetCorefileThreadExtraInfos(tids)) {665        assert(tids.size() == num_threads);666 667        // Find highest tid value.668        lldb::tid_t highest_tid = 0;669        for (uint32_t i = 0; i < num_threads; i++) {670          if (tids[i] != LLDB_INVALID_THREAD_ID && tids[i] > highest_tid)671            highest_tid = tids[i];672        }673        lldb::tid_t current_unused_tid = highest_tid + 1;674        for (uint32_t i = 0; i < num_threads; i++) {675          if (tids[i] == LLDB_INVALID_THREAD_ID) {676            tids[i] = current_unused_tid++;677          }678        }679      } else {680        // No metadata, insert numbers sequentially from 0.681        for (uint32_t i = 0; i < num_threads; i++) {682          tids.push_back(i);683        }684      }685 686      for (uint32_t i = 0; i < num_threads; i++) {687        ThreadSP thread_sp =688            std::make_shared<ThreadMachCore>(*this, tids[i], i);689        new_thread_list.AddThread(thread_sp);690      }691    }692  } else {693    const uint32_t num_threads = old_thread_list.GetSize(false);694    for (uint32_t i = 0; i < num_threads; ++i)695      new_thread_list.AddThread(old_thread_list.GetThreadAtIndex(i, false));696  }697  return new_thread_list.GetSize(false) > 0;698}699 700void ProcessMachCore::RefreshStateAfterStop() {701  // Let all threads recover from stopping and do any clean up based on the702  // previous thread state (if any).703  m_thread_list.RefreshStateAfterStop();704  // SetThreadStopInfo (m_last_stop_packet);705}706 707Status ProcessMachCore::DoDestroy() { return Status(); }708 709// Process Queries710 711bool ProcessMachCore::IsAlive() { return true; }712 713bool ProcessMachCore::WarnBeforeDetach() const { return false; }714 715// Process Memory716size_t ProcessMachCore::ReadMemory(addr_t addr, void *buf, size_t size,717                                   Status &error) {718  // Don't allow the caching that lldb_private::Process::ReadMemory does since719  // in core files we have it all cached our our core file anyway.720  return DoReadMemory(FixAnyAddress(addr), buf, size, error);721}722 723size_t ProcessMachCore::DoReadMemory(addr_t addr, void *buf, size_t size,724                                     Status &error) {725  ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();726  size_t bytes_read = 0;727 728  if (core_objfile) {729    // Segments are not always contiguous in mach-o core files. We have core730    // files that have segments like:731    //            Address    Size       File off   File size732    //            ---------- ---------- ---------- ----------733    // LC_SEGMENT 0x000f6000 0x00001000 0x1d509ee8 0x00001000 --- ---   0734    // 0x00000000 __TEXT LC_SEGMENT 0x0f600000 0x00100000 0x1d50aee8 0x00100000735    // --- ---   0 0x00000000 __TEXT LC_SEGMENT 0x000f7000 0x00001000736    // 0x1d60aee8 0x00001000 --- ---   0 0x00000000 __TEXT737    //738    // Any if the user executes the following command:739    //740    // (lldb) mem read 0xf6ff0741    //742    // We would attempt to read 32 bytes from 0xf6ff0 but would only get 16743    // unless we loop through consecutive memory ranges that are contiguous in744    // the address space, but not in the file data.745    while (bytes_read < size) {746      const addr_t curr_addr = addr + bytes_read;747      const VMRangeToFileOffset::Entry *core_memory_entry =748          m_core_aranges.FindEntryThatContains(curr_addr);749 750      if (core_memory_entry) {751        const addr_t offset = curr_addr - core_memory_entry->GetRangeBase();752        const addr_t bytes_left = core_memory_entry->GetRangeEnd() - curr_addr;753        const size_t bytes_to_read =754            std::min(size - bytes_read, (size_t)bytes_left);755        const size_t curr_bytes_read = core_objfile->CopyData(756            core_memory_entry->data.GetRangeBase() + offset, bytes_to_read,757            (char *)buf + bytes_read);758        if (curr_bytes_read == 0)759          break;760        bytes_read += curr_bytes_read;761      } else {762        // Only set the error if we didn't read any bytes763        if (bytes_read == 0)764          error = Status::FromErrorStringWithFormat(765              "core file does not contain 0x%" PRIx64, curr_addr);766        break;767      }768    }769  }770 771  return bytes_read;772}773 774Status ProcessMachCore::DoGetMemoryRegionInfo(addr_t load_addr,775                                              MemoryRegionInfo &region_info) {776  region_info.Clear();777  const VMRangeToPermissions::Entry *permission_entry =778      m_core_range_infos.FindEntryThatContainsOrFollows(load_addr);779  if (permission_entry) {780    if (permission_entry->Contains(load_addr)) {781      region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase());782      region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd());783      const Flags permissions(permission_entry->data);784      region_info.SetReadable(permissions.Test(ePermissionsReadable)785                                  ? MemoryRegionInfo::eYes786                                  : MemoryRegionInfo::eNo);787      region_info.SetWritable(permissions.Test(ePermissionsWritable)788                                  ? MemoryRegionInfo::eYes789                                  : MemoryRegionInfo::eNo);790      region_info.SetExecutable(permissions.Test(ePermissionsExecutable)791                                    ? MemoryRegionInfo::eYes792                                    : MemoryRegionInfo::eNo);793      region_info.SetMapped(MemoryRegionInfo::eYes);794    } else if (load_addr < permission_entry->GetRangeBase()) {795      region_info.GetRange().SetRangeBase(load_addr);796      region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase());797      region_info.SetReadable(MemoryRegionInfo::eNo);798      region_info.SetWritable(MemoryRegionInfo::eNo);799      region_info.SetExecutable(MemoryRegionInfo::eNo);800      region_info.SetMapped(MemoryRegionInfo::eNo);801    }802    return Status();803  } else {804    // The corefile has no LC_SEGMENT at this virtual address,805    // but see if there is a binary whose Section has been806    // loaded at that address in the current Target.807    Address addr;808    if (GetTarget().ResolveLoadAddress(load_addr, addr)) {809      SectionSP section_sp(addr.GetSection());810      if (section_sp) {811        region_info.GetRange().SetRangeBase(812            section_sp->GetLoadBaseAddress(&GetTarget()));813        region_info.GetRange().SetByteSize(section_sp->GetByteSize());814        if (region_info.GetRange().Contains(load_addr)) {815          region_info.SetLLDBPermissions(section_sp->GetPermissions());816          return Status();817        }818      }819    }820  }821 822  region_info.GetRange().SetRangeBase(load_addr);823  region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);824  region_info.SetReadable(MemoryRegionInfo::eNo);825  region_info.SetWritable(MemoryRegionInfo::eNo);826  region_info.SetExecutable(MemoryRegionInfo::eNo);827  region_info.SetMapped(MemoryRegionInfo::eNo);828  return Status();829}830 831void ProcessMachCore::Clear() { m_thread_list.Clear(); }832 833void ProcessMachCore::Initialize() {834  static llvm::once_flag g_once_flag;835 836  llvm::call_once(g_once_flag, []() {837    PluginManager::RegisterPlugin(GetPluginNameStatic(),838                                  GetPluginDescriptionStatic(), CreateInstance);839  });840}841 842addr_t ProcessMachCore::GetImageInfoAddress() {843  // The DynamicLoader plugin will call back in to this Process844  // method to find the virtual address of one of these:845  //   1. The xnu mach kernel binary Mach-O header846  //   2. The dyld binary Mach-O header847  //   3. dyld's dyld_all_image_infos object848  //849  //  DynamicLoaderMacOSX will accept either the dyld Mach-O header850  //  address or the dyld_all_image_infos interchangably, no need851  //  to distinguish between them.  It disambiguates by the Mach-O852  //  file magic number at the start.853  if (GetCorefilePreference() == eKernelCorefile) {854    if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS)855      return m_mach_kernel_addr;856    if (m_dyld_addr != LLDB_INVALID_ADDRESS)857      return m_dyld_addr;858  } else {859    if (m_dyld_addr != LLDB_INVALID_ADDRESS)860      return m_dyld_addr;861    if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS)862      return m_mach_kernel_addr;863  }864 865  // m_dyld_addr and m_mach_kernel_addr both866  // invalid, return m_dyld_all_image_infos_addr867  // in case it has a useful value.868  return m_dyld_all_image_infos_addr;869}870 871lldb_private::ObjectFile *ProcessMachCore::GetCoreObjectFile() {872  return m_core_module_sp->GetObjectFile();873}874