ProcessMachCore.cpp revision b170aee2daacc83e3d71c3e3acc9d56c89893a7b
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/State.h"
22#include "lldb/Host/Host.h"
23#include "lldb/Target/Target.h"
24#include "lldb/Target/Thread.h"
25
26// Project includes
27#include "ProcessMachCore.h"
28#include "ThreadMachCore.h"
29#include "StopInfoMachException.h"
30
31#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h"
32#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
33
34using namespace lldb;
35using namespace lldb_private;
36
37const char *
38ProcessMachCore::GetPluginNameStatic()
39{
40    return "mach-o-core";
41}
42
43const char *
44ProcessMachCore::GetPluginDescriptionStatic()
45{
46    return "Mach-O core file debugging plug-in.";
47}
48
49void
50ProcessMachCore::Terminate()
51{
52    PluginManager::UnregisterPlugin (ProcessMachCore::CreateInstance);
53}
54
55
56lldb::ProcessSP
57ProcessMachCore::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file)
58{
59    lldb::ProcessSP process_sp;
60    if (crash_file)
61        process_sp.reset(new ProcessMachCore (target, listener, *crash_file));
62    return process_sp;
63}
64
65bool
66ProcessMachCore::CanDebug(Target &target, bool plugin_specified_by_name)
67{
68    if (plugin_specified_by_name)
69        return true;
70
71    // For now we are just making sure the file exists for a given module
72    if (!m_core_module_sp && m_core_file.Exists())
73    {
74        ModuleSpec core_module_spec(m_core_file, target.GetArchitecture());
75        Error error (ModuleList::GetSharedModule (core_module_spec,
76                                                  m_core_module_sp,
77                                                  NULL,
78                                                  NULL,
79                                                  NULL));
80
81        if (m_core_module_sp)
82        {
83            const llvm::Triple &triple_ref = m_core_module_sp->GetArchitecture().GetTriple();
84            if (triple_ref.getVendor() == llvm::Triple::Apple)
85            {
86                ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
87                if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile)
88                    return true;
89            }
90        }
91    }
92    return false;
93}
94
95//----------------------------------------------------------------------
96// ProcessMachCore constructor
97//----------------------------------------------------------------------
98ProcessMachCore::ProcessMachCore(Target& target, Listener &listener, const FileSpec &core_file) :
99    Process (target, listener),
100    m_core_aranges (),
101    m_core_module_sp (),
102    m_core_file (core_file),
103    m_dyld_addr (LLDB_INVALID_ADDRESS),
104    m_dyld_plugin_name ()
105{
106}
107
108//----------------------------------------------------------------------
109// Destructor
110//----------------------------------------------------------------------
111ProcessMachCore::~ProcessMachCore()
112{
113    Clear();
114    // We need to call finalize on the process before destroying ourselves
115    // to make sure all of the broadcaster cleanup goes as planned. If we
116    // destruct this class, then Process::~Process() might have problems
117    // trying to fully destroy the broadcaster.
118    Finalize();
119}
120
121//----------------------------------------------------------------------
122// PluginInterface
123//----------------------------------------------------------------------
124const char *
125ProcessMachCore::GetPluginName()
126{
127    return "Process debugging plug-in that loads mach-o core files.";
128}
129
130const char *
131ProcessMachCore::GetShortPluginName()
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.16llx: 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.16llx: 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.16llx: 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    SectionList *section_list = core_objfile->GetSectionList();
217    if (section_list == NULL)
218    {
219        error.SetErrorString ("core file has no sections");
220        return error;
221    }
222
223    const uint32_t num_sections = section_list->GetNumSections(0);
224    if (num_sections == 0)
225    {
226        error.SetErrorString ("core file has no sections");
227        return error;
228    }
229
230    llvm::MachO::mach_header header;
231    DataExtractor data (&header,
232                        sizeof(header),
233                        m_core_module_sp->GetArchitecture().GetByteOrder(),
234                        m_core_module_sp->GetArchitecture().GetAddressByteSize());
235
236    bool ranges_are_sorted = true;
237    addr_t vm_addr = 0;
238    for (uint32_t i=0; i<num_sections; ++i)
239    {
240        Section *section = section_list->GetSectionAtIndex (i).get();
241        if (section)
242        {
243            lldb::addr_t section_vm_addr = section->GetFileAddress();
244            FileRange file_range (section->GetFileOffset(), section->GetFileSize());
245            VMRangeToFileOffset::Entry range_entry (section_vm_addr,
246                                                    section->GetByteSize(),
247                                                    file_range);
248
249            if (vm_addr > section_vm_addr)
250                ranges_are_sorted = false;
251            vm_addr = section->GetFileAddress();
252            VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
253//            printf ("LC_SEGMENT[%u] arange=[0x%16.16llx - 0x%16.16llx), frange=[0x%8.8x - 0x%8.8x)\n",
254//                    i,
255//                    range_entry.GetRangeBase(),
256//                    range_entry.GetRangeEnd(),
257//                    range_entry.data.GetRangeBase(),
258//                    range_entry.data.GetRangeEnd());
259
260            if (last_entry &&
261                last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
262                last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase())
263            {
264                last_entry->SetRangeEnd (range_entry.GetRangeEnd());
265                last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd());
266                //puts("combine");
267            }
268            else
269            {
270                m_core_aranges.Append(range_entry);
271            }
272
273            // After we have added this section to our m_core_aranges map,
274            // we can check the start of the section to see if it might
275            // contain dyld for user space apps, or the mach kernel file
276            // for kernel cores.
277            if (m_dyld_addr == LLDB_INVALID_ADDRESS)
278                GetDynamicLoaderAddress (section_vm_addr);
279        }
280    }
281    if (!ranges_are_sorted)
282    {
283        m_core_aranges.Sort();
284    }
285
286    // Even if the architecture is set in the target, we need to override
287    // it to match the core file which is always single arch.
288    ArchSpec arch (m_core_module_sp->GetArchitecture());
289    if (arch.GetCore() == ArchSpec::eCore_x86_32_i486)
290    {
291        arch.SetTriple ("i386", m_target.GetPlatform().get());
292    }
293    if (arch.IsValid())
294        m_target.SetArchitecture(arch);
295
296    if (m_dyld_addr == LLDB_INVALID_ADDRESS)
297    {
298        // Check the magic kernel address for the mach image header address in case
299        // it is there.
300        if (arch.GetAddressByteSize() == 8)
301        {
302            Error header_addr_error;
303            addr_t header_addr = ReadPointerFromMemory (0xffffff8000002010ull, header_addr_error);
304            if (header_addr != LLDB_INVALID_ADDRESS)
305                GetDynamicLoaderAddress (header_addr);
306        }
307
308//        if (m_dyld_addr == LLDB_INVALID_ADDRESS)
309//        {
310//            // We haven't found our dyld or mach_kernel yet,
311//            // so we need to exhaustively look
312//            const size_t num_core_aranges = m_core_aranges.GetSize();
313//            bool done = false;
314//            for (size_t i=0; !done && i<num_core_aranges; ++i)
315//            {
316//                const addr_t start_vaddr = m_core_aranges.GetEntryRef(i).GetRangeBase();
317//                const addr_t end_vaddr = m_core_aranges.GetEntryRef(i).GetRangeEnd();
318//                //            printf("core_arange[%u] [0x%16.16llx - 0x%16.16llx)\n", (uint32_t)i, start_vaddr, end_vaddr);
319//
320//                for (addr_t vaddr = start_vaddr; !done && start_vaddr < end_vaddr; vaddr += 0x1000)
321//                {
322//                    done = GetDynamicLoaderAddress (vaddr);
323//                }
324//            }
325//        }
326    }
327
328    return error;
329}
330
331lldb_private::DynamicLoader *
332ProcessMachCore::GetDynamicLoader ()
333{
334    if (m_dyld_ap.get() == NULL)
335        m_dyld_ap.reset (DynamicLoader::FindPlugin(this, m_dyld_plugin_name.empty() ? NULL : m_dyld_plugin_name.c_str()));
336    return m_dyld_ap.get();
337}
338
339bool
340ProcessMachCore::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
341{
342    if (old_thread_list.GetSize(false) == 0)
343    {
344        // Make up the thread the first time this is called so we can setup our one and only
345        // core thread state.
346        ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
347
348        if (core_objfile)
349        {
350            const uint32_t num_threads = core_objfile->GetNumThreadContexts ();
351            for (lldb::tid_t tid = 0; tid < num_threads; ++tid)
352            {
353                ThreadSP thread_sp(new ThreadMachCore (shared_from_this(), tid));
354                new_thread_list.AddThread (thread_sp);
355            }
356        }
357    }
358    else
359    {
360        const uint32_t num_threads = old_thread_list.GetSize(false);
361        for (uint32_t i=0; i<num_threads; ++i)
362            new_thread_list.AddThread (old_thread_list.GetThreadAtIndex (i));
363    }
364    return new_thread_list.GetSize(false) > 0;
365}
366
367void
368ProcessMachCore::RefreshStateAfterStop ()
369{
370    // Let all threads recover from stopping and do any clean up based
371    // on the previous thread state (if any).
372    m_thread_list.RefreshStateAfterStop();
373    //SetThreadStopInfo (m_last_stop_packet);
374}
375
376Error
377ProcessMachCore::DoDestroy ()
378{
379    return Error();
380}
381
382//------------------------------------------------------------------
383// Process Queries
384//------------------------------------------------------------------
385
386bool
387ProcessMachCore::IsAlive ()
388{
389    return true;
390}
391
392//------------------------------------------------------------------
393// Process Memory
394//------------------------------------------------------------------
395size_t
396ProcessMachCore::ReadMemory (addr_t addr, void *buf, size_t size, Error &error)
397{
398    // Don't allow the caching that lldb_private::Process::ReadMemory does
399    // since in core files we have it all cached our our core file anyway.
400    return DoReadMemory (addr, buf, size, error);
401}
402
403size_t
404ProcessMachCore::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
405{
406    ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
407
408    if (core_objfile)
409    {
410        const VMRangeToFileOffset::Entry *core_memory_entry = m_core_aranges.FindEntryThatContains (addr);
411        if (core_memory_entry)
412        {
413            const addr_t offset = addr - core_memory_entry->GetRangeBase();
414            const addr_t bytes_left = core_memory_entry->GetRangeEnd() - addr;
415            size_t bytes_to_read = size;
416            if (bytes_to_read > bytes_left)
417                bytes_to_read = bytes_left;
418            return core_objfile->CopyData (core_memory_entry->data.GetRangeBase() + offset, bytes_to_read, buf);
419        }
420        else
421        {
422            error.SetErrorStringWithFormat ("core file does not contain 0x%llx", addr);
423        }
424    }
425    return 0;
426}
427
428void
429ProcessMachCore::Clear()
430{
431    m_thread_list.Clear();
432}
433
434void
435ProcessMachCore::Initialize()
436{
437    static bool g_initialized = false;
438
439    if (g_initialized == false)
440    {
441        g_initialized = true;
442        PluginManager::RegisterPlugin (GetPluginNameStatic(),
443                                       GetPluginDescriptionStatic(),
444                                       CreateInstance);
445    }
446}
447
448addr_t
449ProcessMachCore::GetImageInfoAddress()
450{
451    return m_dyld_addr;
452}
453
454
455