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
39using namespace lldb;
40using namespace lldb_private;
41
42ConstString
43ProcessMachCore::GetPluginNameStatic()
44{
45    static ConstString g_name("mach-o-core");
46    return g_name;
47}
48
49const char *
50ProcessMachCore::GetPluginDescriptionStatic()
51{
52    return "Mach-O core file debugging plug-in.";
53}
54
55void
56ProcessMachCore::Terminate()
57{
58    PluginManager::UnregisterPlugin (ProcessMachCore::CreateInstance);
59}
60
61
62lldb::ProcessSP
63ProcessMachCore::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
71bool
72ProcessMachCore::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//----------------------------------------------------------------------
104ProcessMachCore::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//----------------------------------------------------------------------
117ProcessMachCore::~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//----------------------------------------------------------------------
130ConstString
131ProcessMachCore::GetPluginName()
132{
133    return GetPluginNameStatic();
134}
135
136uint32_t
137ProcessMachCore::GetPluginVersion()
138{
139    return 1;
140}
141
142bool
143ProcessMachCore::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//----------------------------------------------------------------------
200Error
201ProcessMachCore::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
332lldb_private::DynamicLoader *
333ProcessMachCore::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
340bool
341ProcessMachCore::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
368void
369ProcessMachCore::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
377Error
378ProcessMachCore::DoDestroy ()
379{
380    return Error();
381}
382
383//------------------------------------------------------------------
384// Process Queries
385//------------------------------------------------------------------
386
387bool
388ProcessMachCore::IsAlive ()
389{
390    return true;
391}
392
393bool
394ProcessMachCore::WarnBeforeDetach () const
395{
396    return false;
397}
398
399//------------------------------------------------------------------
400// Process Memory
401//------------------------------------------------------------------
402size_t
403ProcessMachCore::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
410size_t
411ProcessMachCore::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
435void
436ProcessMachCore::Clear()
437{
438    m_thread_list.Clear();
439}
440
441void
442ProcessMachCore::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
455addr_t
456ProcessMachCore::GetImageInfoAddress()
457{
458    return m_dyld_addr;
459}
460
461
462lldb_private::ObjectFile *
463ProcessMachCore::GetCoreObjectFile ()
464{
465    return m_core_module_sp->GetObjectFile();
466}
467