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