Home | History | Annotate | Download | only in mach-core
      1 //===-- ProcessMachCore.cpp ------------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 // C Includes
     11 #include <errno.h>
     12 #include <stdlib.h>
     13 
     14 // C++ Includes
     15 #include "llvm/Support/MachO.h"
     16 #include "llvm/Support/MathExtras.h"
     17 
     18 // Other libraries and framework includes
     19 #include "lldb/Core/Debugger.h"
     20 #include "lldb/Core/PluginManager.h"
     21 #include "lldb/Core/Module.h"
     22 #include "lldb/Core/ModuleSpec.h"
     23 #include "lldb/Core/Section.h"
     24 #include "lldb/Core/State.h"
     25 #include "lldb/Host/Host.h"
     26 #include "lldb/Symbol/ObjectFile.h"
     27 #include "lldb/Target/Target.h"
     28 #include "lldb/Target/Thread.h"
     29 
     30 // Project includes
     31 #include "ProcessMachCore.h"
     32 #include "ThreadMachCore.h"
     33 #include "StopInfoMachException.h"
     34 
     35 // Needed for the plug-in names for the dynamic loaders.
     36 #include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h"
     37 #include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
     38 
     39 using namespace lldb;
     40 using namespace lldb_private;
     41 
     42 ConstString
     43 ProcessMachCore::GetPluginNameStatic()
     44 {
     45     static ConstString g_name("mach-o-core");
     46     return g_name;
     47 }
     48 
     49 const char *
     50 ProcessMachCore::GetPluginDescriptionStatic()
     51 {
     52     return "Mach-O core file debugging plug-in.";
     53 }
     54 
     55 void
     56 ProcessMachCore::Terminate()
     57 {
     58     PluginManager::UnregisterPlugin (ProcessMachCore::CreateInstance);
     59 }
     60 
     61 
     62 lldb::ProcessSP
     63 ProcessMachCore::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file)
     64 {
     65     lldb::ProcessSP process_sp;
     66     if (crash_file)
     67         process_sp.reset(new ProcessMachCore (target, listener, *crash_file));
     68     return process_sp;
     69 }
     70 
     71 bool
     72 ProcessMachCore::CanDebug(Target &target, bool plugin_specified_by_name)
     73 {
     74     if (plugin_specified_by_name)
     75         return true;
     76 
     77     // For now we are just making sure the file exists for a given module
     78     if (!m_core_module_sp && m_core_file.Exists())
     79     {
     80         ModuleSpec core_module_spec(m_core_file, target.GetArchitecture());
     81         Error error (ModuleList::GetSharedModule (core_module_spec,
     82                                                   m_core_module_sp,
     83                                                   NULL,
     84                                                   NULL,
     85                                                   NULL));
     86 
     87         if (m_core_module_sp)
     88         {
     89             const llvm::Triple &triple_ref = m_core_module_sp->GetArchitecture().GetTriple();
     90             if (triple_ref.getVendor() == llvm::Triple::Apple)
     91             {
     92                 ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
     93                 if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile)
     94                     return true;
     95             }
     96         }
     97     }
     98     return false;
     99 }
    100 
    101 //----------------------------------------------------------------------
    102 // ProcessMachCore constructor
    103 //----------------------------------------------------------------------
    104 ProcessMachCore::ProcessMachCore(Target& target, Listener &listener, const FileSpec &core_file) :
    105     Process (target, listener),
    106     m_core_aranges (),
    107     m_core_module_sp (),
    108     m_core_file (core_file),
    109     m_dyld_addr (LLDB_INVALID_ADDRESS),
    110     m_dyld_plugin_name ()
    111 {
    112 }
    113 
    114 //----------------------------------------------------------------------
    115 // Destructor
    116 //----------------------------------------------------------------------
    117 ProcessMachCore::~ProcessMachCore()
    118 {
    119     Clear();
    120     // We need to call finalize on the process before destroying ourselves
    121     // to make sure all of the broadcaster cleanup goes as planned. If we
    122     // destruct this class, then Process::~Process() might have problems
    123     // trying to fully destroy the broadcaster.
    124     Finalize();
    125 }
    126 
    127 //----------------------------------------------------------------------
    128 // PluginInterface
    129 //----------------------------------------------------------------------
    130 ConstString
    131 ProcessMachCore::GetPluginName()
    132 {
    133     return GetPluginNameStatic();
    134 }
    135 
    136 uint32_t
    137 ProcessMachCore::GetPluginVersion()
    138 {
    139     return 1;
    140 }
    141 
    142 bool
    143 ProcessMachCore::GetDynamicLoaderAddress (lldb::addr_t addr)
    144 {
    145     llvm::MachO::mach_header header;
    146     Error error;
    147     if (DoReadMemory (addr, &header, sizeof(header), error) != sizeof(header))
    148         return false;
    149     if (header.magic == llvm::MachO::HeaderMagic32Swapped ||
    150         header.magic == llvm::MachO::HeaderMagic64Swapped)
    151     {
    152         header.magic        = llvm::ByteSwap_32(header.magic);
    153         header.cputype      = llvm::ByteSwap_32(header.cputype);
    154         header.cpusubtype   = llvm::ByteSwap_32(header.cpusubtype);
    155         header.filetype     = llvm::ByteSwap_32(header.filetype);
    156         header.ncmds        = llvm::ByteSwap_32(header.ncmds);
    157         header.sizeofcmds   = llvm::ByteSwap_32(header.sizeofcmds);
    158         header.flags        = llvm::ByteSwap_32(header.flags);
    159     }
    160 
    161     // TODO: swap header if needed...
    162     //printf("0x%16.16" PRIx64 ": magic = 0x%8.8x, file_type= %u\n", vaddr, header.magic, header.filetype);
    163     if (header.magic == llvm::MachO::HeaderMagic32 ||
    164         header.magic == llvm::MachO::HeaderMagic64)
    165     {
    166         // Check MH_EXECUTABLE to see if we can find the mach image
    167         // that contains the shared library list. The dynamic loader
    168         // (dyld) is what contains the list for user applications,
    169         // and the mach kernel contains a global that has the list
    170         // of kexts to load
    171         switch (header.filetype)
    172         {
    173         case llvm::MachO::HeaderFileTypeDynamicLinkEditor:
    174             //printf("0x%16.16" PRIx64 ": file_type = MH_DYLINKER\n", vaddr);
    175             // Address of dyld "struct mach_header" in the core file
    176             m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
    177             m_dyld_addr = addr;
    178             return true;
    179 
    180         case llvm::MachO::HeaderFileTypeExecutable:
    181             //printf("0x%16.16" PRIx64 ": file_type = MH_EXECUTE\n", vaddr);
    182             // Check MH_EXECUTABLE file types to see if the dynamic link object flag
    183             // is NOT set. If it isn't, then we have a mach_kernel.
    184             if ((header.flags & llvm::MachO::HeaderFlagBitIsDynamicLinkObject) == 0)
    185             {
    186                 m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
    187                 // Address of the mach kernel "struct mach_header" in the core file.
    188                 m_dyld_addr = addr;
    189                 return true;
    190             }
    191             break;
    192         }
    193     }
    194     return false;
    195 }
    196 
    197 //----------------------------------------------------------------------
    198 // Process Control
    199 //----------------------------------------------------------------------
    200 Error
    201 ProcessMachCore::DoLoadCore ()
    202 {
    203     Error error;
    204     if (!m_core_module_sp)
    205     {
    206         error.SetErrorString ("invalid core module");
    207         return error;
    208     }
    209 
    210     ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
    211     if (core_objfile == NULL)
    212     {
    213         error.SetErrorString ("invalid core object file");
    214         return error;
    215     }
    216 
    217     if (core_objfile->GetNumThreadContexts() == 0)
    218     {
    219         error.SetErrorString ("core file doesn't contain any LC_THREAD load commands, or the LC_THREAD architecture is not supported in this lldb");
    220         return error;
    221     }
    222 
    223     SectionList *section_list = core_objfile->GetSectionList();
    224     if (section_list == NULL)
    225     {
    226         error.SetErrorString ("core file has no sections");
    227         return error;
    228     }
    229 
    230     const uint32_t num_sections = section_list->GetNumSections(0);
    231     if (num_sections == 0)
    232     {
    233         error.SetErrorString ("core file has no sections");
    234         return error;
    235     }
    236 
    237     SetCanJIT(false);
    238 
    239     llvm::MachO::mach_header header;
    240     DataExtractor data (&header,
    241                         sizeof(header),
    242                         m_core_module_sp->GetArchitecture().GetByteOrder(),
    243                         m_core_module_sp->GetArchitecture().GetAddressByteSize());
    244 
    245     bool ranges_are_sorted = true;
    246     addr_t vm_addr = 0;
    247     for (uint32_t i=0; i<num_sections; ++i)
    248     {
    249         Section *section = section_list->GetSectionAtIndex (i).get();
    250         if (section)
    251         {
    252             lldb::addr_t section_vm_addr = section->GetFileAddress();
    253             FileRange file_range (section->GetFileOffset(), section->GetFileSize());
    254             VMRangeToFileOffset::Entry range_entry (section_vm_addr,
    255                                                     section->GetByteSize(),
    256                                                     file_range);
    257 
    258             if (vm_addr > section_vm_addr)
    259                 ranges_are_sorted = false;
    260             vm_addr = section->GetFileAddress();
    261             VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
    262 //            printf ("LC_SEGMENT[%u] arange=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), frange=[0x%8.8x - 0x%8.8x)\n",
    263 //                    i,
    264 //                    range_entry.GetRangeBase(),
    265 //                    range_entry.GetRangeEnd(),
    266 //                    range_entry.data.GetRangeBase(),
    267 //                    range_entry.data.GetRangeEnd());
    268 
    269             if (last_entry &&
    270                 last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
    271                 last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase())
    272             {
    273                 last_entry->SetRangeEnd (range_entry.GetRangeEnd());
    274                 last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd());
    275                 //puts("combine");
    276             }
    277             else
    278             {
    279                 m_core_aranges.Append(range_entry);
    280             }
    281 
    282             // After we have added this section to our m_core_aranges map,
    283             // we can check the start of the section to see if it might
    284             // contain dyld for user space apps, or the mach kernel file
    285             // for kernel cores.
    286             if (m_dyld_addr == LLDB_INVALID_ADDRESS)
    287                 GetDynamicLoaderAddress (section_vm_addr);
    288         }
    289     }
    290     if (!ranges_are_sorted)
    291     {
    292         m_core_aranges.Sort();
    293     }
    294 
    295     // Even if the architecture is set in the target, we need to override
    296     // it to match the core file which is always single arch.
    297     ArchSpec arch (m_core_module_sp->GetArchitecture());
    298     if (arch.GetCore() == ArchSpec::eCore_x86_32_i486)
    299     {
    300         arch.SetTriple ("i386", m_target.GetPlatform().get());
    301     }
    302     if (arch.IsValid())
    303         m_target.SetArchitecture(arch);
    304 
    305     if (m_dyld_addr == LLDB_INVALID_ADDRESS)
    306     {
    307         // We need to locate the main executable in the memory ranges
    308         // we have in the core file. We already checked the first address
    309         // in each memory zone above, so we just need to check each page
    310         // except the first page in each range and stop once we have found
    311         // our main executable
    312         const size_t num_core_aranges = m_core_aranges.GetSize();
    313         for (size_t i=0; i<num_core_aranges && m_dyld_addr == LLDB_INVALID_ADDRESS; ++i)
    314         {
    315             const VMRangeToFileOffset::Entry *entry = m_core_aranges.GetEntryAtIndex(i);
    316             lldb::addr_t section_vm_addr_start = entry->GetRangeBase();
    317             lldb::addr_t section_vm_addr_end = entry->GetRangeEnd();
    318             for (lldb::addr_t section_vm_addr = section_vm_addr_start + 0x1000;
    319                  section_vm_addr < section_vm_addr_end;
    320                  section_vm_addr += 0x1000)
    321             {
    322                 if (GetDynamicLoaderAddress (section_vm_addr))
    323                 {
    324                     break;
    325                 }
    326             }
    327         }
    328     }
    329     return error;
    330 }
    331 
    332 lldb_private::DynamicLoader *
    333 ProcessMachCore::GetDynamicLoader ()
    334 {
    335     if (m_dyld_ap.get() == NULL)
    336         m_dyld_ap.reset (DynamicLoader::FindPlugin(this, m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString()));
    337     return m_dyld_ap.get();
    338 }
    339 
    340 bool
    341 ProcessMachCore::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
    342 {
    343     if (old_thread_list.GetSize(false) == 0)
    344     {
    345         // Make up the thread the first time this is called so we can setup our one and only
    346         // core thread state.
    347         ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
    348 
    349         if (core_objfile)
    350         {
    351             const uint32_t num_threads = core_objfile->GetNumThreadContexts ();
    352             for (lldb::tid_t tid = 0; tid < num_threads; ++tid)
    353             {
    354                 ThreadSP thread_sp(new ThreadMachCore (*this, tid));
    355                 new_thread_list.AddThread (thread_sp);
    356             }
    357         }
    358     }
    359     else
    360     {
    361         const uint32_t num_threads = old_thread_list.GetSize(false);
    362         for (uint32_t i=0; i<num_threads; ++i)
    363             new_thread_list.AddThread (old_thread_list.GetThreadAtIndex (i));
    364     }
    365     return new_thread_list.GetSize(false) > 0;
    366 }
    367 
    368 void
    369 ProcessMachCore::RefreshStateAfterStop ()
    370 {
    371     // Let all threads recover from stopping and do any clean up based
    372     // on the previous thread state (if any).
    373     m_thread_list.RefreshStateAfterStop();
    374     //SetThreadStopInfo (m_last_stop_packet);
    375 }
    376 
    377 Error
    378 ProcessMachCore::DoDestroy ()
    379 {
    380     return Error();
    381 }
    382 
    383 //------------------------------------------------------------------
    384 // Process Queries
    385 //------------------------------------------------------------------
    386 
    387 bool
    388 ProcessMachCore::IsAlive ()
    389 {
    390     return true;
    391 }
    392 
    393 bool
    394 ProcessMachCore::WarnBeforeDetach () const
    395 {
    396     return false;
    397 }
    398 
    399 //------------------------------------------------------------------
    400 // Process Memory
    401 //------------------------------------------------------------------
    402 size_t
    403 ProcessMachCore::ReadMemory (addr_t addr, void *buf, size_t size, Error &error)
    404 {
    405     // Don't allow the caching that lldb_private::Process::ReadMemory does
    406     // since in core files we have it all cached our our core file anyway.
    407     return DoReadMemory (addr, buf, size, error);
    408 }
    409 
    410 size_t
    411 ProcessMachCore::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
    412 {
    413     ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
    414 
    415     if (core_objfile)
    416     {
    417         const VMRangeToFileOffset::Entry *core_memory_entry = m_core_aranges.FindEntryThatContains (addr);
    418         if (core_memory_entry)
    419         {
    420             const addr_t offset = addr - core_memory_entry->GetRangeBase();
    421             const addr_t bytes_left = core_memory_entry->GetRangeEnd() - addr;
    422             size_t bytes_to_read = size;
    423             if (bytes_to_read > bytes_left)
    424                 bytes_to_read = bytes_left;
    425             return core_objfile->CopyData (core_memory_entry->data.GetRangeBase() + offset, bytes_to_read, buf);
    426         }
    427         else
    428         {
    429             error.SetErrorStringWithFormat ("core file does not contain 0x%" PRIx64, addr);
    430         }
    431     }
    432     return 0;
    433 }
    434 
    435 void
    436 ProcessMachCore::Clear()
    437 {
    438     m_thread_list.Clear();
    439 }
    440 
    441 void
    442 ProcessMachCore::Initialize()
    443 {
    444     static bool g_initialized = false;
    445 
    446     if (g_initialized == false)
    447     {
    448         g_initialized = true;
    449         PluginManager::RegisterPlugin (GetPluginNameStatic(),
    450                                        GetPluginDescriptionStatic(),
    451                                        CreateInstance);
    452     }
    453 }
    454 
    455 addr_t
    456 ProcessMachCore::GetImageInfoAddress()
    457 {
    458     return m_dyld_addr;
    459 }
    460 
    461 
    462 lldb_private::ObjectFile *
    463 ProcessMachCore::GetCoreObjectFile ()
    464 {
    465     return m_core_module_sp->GetObjectFile();
    466 }
    467