ProcessMachCore.cpp revision 4952db8c76f619e3d8a0cf13456097128009d67b
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.16llx: 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.16llx: 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.16llx: 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    llvm::MachO::mach_header header;
235    DataExtractor data (&header,
236                        sizeof(header),
237                        m_core_module_sp->GetArchitecture().GetByteOrder(),
238                        m_core_module_sp->GetArchitecture().GetAddressByteSize());
239
240    bool ranges_are_sorted = true;
241    addr_t vm_addr = 0;
242    for (uint32_t i=0; i<num_sections; ++i)
243    {
244        Section *section = section_list->GetSectionAtIndex (i).get();
245        if (section)
246        {
247            lldb::addr_t section_vm_addr = section->GetFileAddress();
248            FileRange file_range (section->GetFileOffset(), section->GetFileSize());
249            VMRangeToFileOffset::Entry range_entry (section_vm_addr,
250                                                    section->GetByteSize(),
251                                                    file_range);
252
253            if (vm_addr > section_vm_addr)
254                ranges_are_sorted = false;
255            vm_addr = section->GetFileAddress();
256            VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
257//            printf ("LC_SEGMENT[%u] arange=[0x%16.16llx - 0x%16.16llx), frange=[0x%8.8x - 0x%8.8x)\n",
258//                    i,
259//                    range_entry.GetRangeBase(),
260//                    range_entry.GetRangeEnd(),
261//                    range_entry.data.GetRangeBase(),
262//                    range_entry.data.GetRangeEnd());
263
264            if (last_entry &&
265                last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
266                last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase())
267            {
268                last_entry->SetRangeEnd (range_entry.GetRangeEnd());
269                last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd());
270                //puts("combine");
271            }
272            else
273            {
274                m_core_aranges.Append(range_entry);
275            }
276
277            // After we have added this section to our m_core_aranges map,
278            // we can check the start of the section to see if it might
279            // contain dyld for user space apps, or the mach kernel file
280            // for kernel cores.
281            if (m_dyld_addr == LLDB_INVALID_ADDRESS)
282                GetDynamicLoaderAddress (section_vm_addr);
283        }
284    }
285    if (!ranges_are_sorted)
286    {
287        m_core_aranges.Sort();
288    }
289
290    // Even if the architecture is set in the target, we need to override
291    // it to match the core file which is always single arch.
292    ArchSpec arch (m_core_module_sp->GetArchitecture());
293    if (arch.GetCore() == ArchSpec::eCore_x86_32_i486)
294    {
295        arch.SetTriple ("i386", m_target.GetPlatform().get());
296    }
297    if (arch.IsValid())
298        m_target.SetArchitecture(arch);
299
300    if (m_dyld_addr == LLDB_INVALID_ADDRESS)
301    {
302        // Check the magic kernel address for the mach image header address in case
303        // it is there.
304        if (arch.GetAddressByteSize() == 8)
305        {
306            Error header_addr_error;
307            addr_t header_addr = ReadPointerFromMemory (0xffffff8000002010ull, header_addr_error);
308            if (header_addr != LLDB_INVALID_ADDRESS)
309                GetDynamicLoaderAddress (header_addr);
310        }
311        else
312        {
313            Error header_addr_error;
314            addr_t header_addr = ReadPointerFromMemory (0xffff0110, header_addr_error);
315            if (header_addr != LLDB_INVALID_ADDRESS)
316                GetDynamicLoaderAddress (header_addr);
317        }
318    }
319
320    return error;
321}
322
323lldb_private::DynamicLoader *
324ProcessMachCore::GetDynamicLoader ()
325{
326    if (m_dyld_ap.get() == NULL)
327        m_dyld_ap.reset (DynamicLoader::FindPlugin(this, m_dyld_plugin_name.empty() ? NULL : m_dyld_plugin_name.c_str()));
328    return m_dyld_ap.get();
329}
330
331bool
332ProcessMachCore::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
333{
334    if (old_thread_list.GetSize(false) == 0)
335    {
336        // Make up the thread the first time this is called so we can setup our one and only
337        // core thread state.
338        ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
339
340        if (core_objfile)
341        {
342            const uint32_t num_threads = core_objfile->GetNumThreadContexts ();
343            for (lldb::tid_t tid = 0; tid < num_threads; ++tid)
344            {
345                ThreadSP thread_sp(new ThreadMachCore (shared_from_this(), tid));
346                new_thread_list.AddThread (thread_sp);
347            }
348        }
349    }
350    else
351    {
352        const uint32_t num_threads = old_thread_list.GetSize(false);
353        for (uint32_t i=0; i<num_threads; ++i)
354            new_thread_list.AddThread (old_thread_list.GetThreadAtIndex (i));
355    }
356    return new_thread_list.GetSize(false) > 0;
357}
358
359void
360ProcessMachCore::RefreshStateAfterStop ()
361{
362    // Let all threads recover from stopping and do any clean up based
363    // on the previous thread state (if any).
364    m_thread_list.RefreshStateAfterStop();
365    //SetThreadStopInfo (m_last_stop_packet);
366}
367
368Error
369ProcessMachCore::DoDestroy ()
370{
371    return Error();
372}
373
374//------------------------------------------------------------------
375// Process Queries
376//------------------------------------------------------------------
377
378bool
379ProcessMachCore::IsAlive ()
380{
381    return true;
382}
383
384//------------------------------------------------------------------
385// Process Memory
386//------------------------------------------------------------------
387size_t
388ProcessMachCore::ReadMemory (addr_t addr, void *buf, size_t size, Error &error)
389{
390    // Don't allow the caching that lldb_private::Process::ReadMemory does
391    // since in core files we have it all cached our our core file anyway.
392    return DoReadMemory (addr, buf, size, error);
393}
394
395size_t
396ProcessMachCore::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
397{
398    ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
399
400    if (core_objfile)
401    {
402        const VMRangeToFileOffset::Entry *core_memory_entry = m_core_aranges.FindEntryThatContains (addr);
403        if (core_memory_entry)
404        {
405            const addr_t offset = addr - core_memory_entry->GetRangeBase();
406            const addr_t bytes_left = core_memory_entry->GetRangeEnd() - addr;
407            size_t bytes_to_read = size;
408            if (bytes_to_read > bytes_left)
409                bytes_to_read = bytes_left;
410            return core_objfile->CopyData (core_memory_entry->data.GetRangeBase() + offset, bytes_to_read, buf);
411        }
412        else
413        {
414            error.SetErrorStringWithFormat ("core file does not contain 0x%llx", addr);
415        }
416    }
417    return 0;
418}
419
420void
421ProcessMachCore::Clear()
422{
423    m_thread_list.Clear();
424}
425
426void
427ProcessMachCore::Initialize()
428{
429    static bool g_initialized = false;
430
431    if (g_initialized == false)
432    {
433        g_initialized = true;
434        PluginManager::RegisterPlugin (GetPluginNameStatic(),
435                                       GetPluginDescriptionStatic(),
436                                       CreateInstance);
437    }
438}
439
440addr_t
441ProcessMachCore::GetImageInfoAddress()
442{
443    return m_dyld_addr;
444}
445
446
447lldb_private::ObjectFile *
448ProcessMachCore::GetCoreObjectFile ()
449{
450    return m_core_module_sp->GetObjectFile();
451}
452