DynamicLoaderDarwinKernel.cpp revision 4a55d75b00a2956f5a26f15c03137c090d142a38
1//===-- DynamicLoaderDarwinKernel.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#include "lldb/Breakpoint/StoppointCallbackContext.h"
11#include "lldb/Core/DataBuffer.h"
12#include "lldb/Core/DataBufferHeap.h"
13#include "lldb/Core/Debugger.h"
14#include "lldb/Core/Log.h"
15#include "lldb/Core/Module.h"
16#include "lldb/Core/ModuleSpec.h"
17#include "lldb/Core/ModuleSpec.h"
18#include "lldb/Core/PluginManager.h"
19#include "lldb/Core/Section.h"
20#include "lldb/Core/State.h"
21#include "lldb/Host/Symbols.h"
22#include "lldb/Symbol/ObjectFile.h"
23#include "lldb/Target/RegisterContext.h"
24#include "lldb/Target/StackFrame.h"
25#include "lldb/Target/Target.h"
26#include "lldb/Target/Thread.h"
27#include "lldb/Target/ThreadPlanRunToAddress.h"
28
29
30#include "DynamicLoaderDarwinKernel.h"
31
32//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
33#ifdef ENABLE_DEBUG_PRINTF
34#include <stdio.h>
35#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
36#else
37#define DEBUG_PRINTF(fmt, ...)
38#endif
39
40using namespace lldb;
41using namespace lldb_private;
42
43//----------------------------------------------------------------------
44// Create an instance of this class. This function is filled into
45// the plugin info class that gets handed out by the plugin factory and
46// allows the lldb to instantiate an instance of this class.
47//----------------------------------------------------------------------
48DynamicLoader *
49DynamicLoaderDarwinKernel::CreateInstance (Process* process, bool force)
50{
51    bool create = force;
52    if (!create)
53    {
54        Module* exe_module = process->GetTarget().GetExecutableModulePointer();
55        if (exe_module)
56        {
57            ObjectFile *object_file = exe_module->GetObjectFile();
58            if (object_file)
59            {
60                create = (object_file->GetStrata() == ObjectFile::eStrataKernel);
61            }
62        }
63
64        if (create)
65        {
66            const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
67            switch (triple_ref.getOS())
68            {
69                case llvm::Triple::Darwin:
70                case llvm::Triple::MacOSX:
71                case llvm::Triple::IOS:
72                    create = triple_ref.getVendor() == llvm::Triple::Apple;
73                    break;
74                default:
75                    create = false;
76                    break;
77            }
78        }
79    }
80
81    if (create)
82    {
83        process->SetCanJIT(false);
84        return new DynamicLoaderDarwinKernel (process);
85    }
86    return NULL;
87}
88
89//----------------------------------------------------------------------
90// Constructor
91//----------------------------------------------------------------------
92DynamicLoaderDarwinKernel::DynamicLoaderDarwinKernel (Process* process) :
93    DynamicLoader(process),
94    m_kernel(),
95    m_kext_summary_header_ptr_addr (),
96    m_kext_summary_header_addr (),
97    m_kext_summary_header (),
98    m_kext_summaries(),
99    m_mutex(Mutex::eMutexTypeRecursive),
100    m_break_id (LLDB_INVALID_BREAK_ID)
101{
102}
103
104//----------------------------------------------------------------------
105// Destructor
106//----------------------------------------------------------------------
107DynamicLoaderDarwinKernel::~DynamicLoaderDarwinKernel()
108{
109    Clear(true);
110}
111
112void
113DynamicLoaderDarwinKernel::UpdateIfNeeded()
114{
115    LoadKernelModuleIfNeeded();
116    SetNotificationBreakpointIfNeeded ();
117}
118//------------------------------------------------------------------
119/// Called after attaching a process.
120///
121/// Allow DynamicLoader plug-ins to execute some code after
122/// attaching to a process.
123//------------------------------------------------------------------
124void
125DynamicLoaderDarwinKernel::DidAttach ()
126{
127    PrivateInitialize(m_process);
128    UpdateIfNeeded();
129}
130
131//------------------------------------------------------------------
132/// Called after attaching a process.
133///
134/// Allow DynamicLoader plug-ins to execute some code after
135/// attaching to a process.
136//------------------------------------------------------------------
137void
138DynamicLoaderDarwinKernel::DidLaunch ()
139{
140    PrivateInitialize(m_process);
141    UpdateIfNeeded();
142}
143
144
145//----------------------------------------------------------------------
146// Clear out the state of this class.
147//----------------------------------------------------------------------
148void
149DynamicLoaderDarwinKernel::Clear (bool clear_process)
150{
151    Mutex::Locker locker(m_mutex);
152
153    if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
154        m_process->ClearBreakpointSiteByID(m_break_id);
155
156    if (clear_process)
157        m_process = NULL;
158    m_kernel.Clear(false);
159    m_kext_summary_header_ptr_addr.Clear();
160    m_kext_summary_header_addr.Clear();
161    m_kext_summaries.clear();
162    m_break_id = LLDB_INVALID_BREAK_ID;
163}
164
165
166bool
167DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::LoadImageAtFileAddress (Process *process)
168{
169    if (IsLoaded())
170        return true;
171
172    if (module_sp)
173    {
174        bool changed = false;
175        if (module_sp->SetLoadAddress (process->GetTarget(), 0, changed))
176            load_process_stop_id = process->GetStopID();
177    }
178    return false;
179}
180
181bool
182DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::LoadImageUsingMemoryModule (Process *process)
183{
184    if (IsLoaded())
185        return true;
186
187    bool uuid_is_valid = uuid.IsValid();
188    bool memory_module_is_kernel = false;
189
190    Target &target = process->GetTarget();
191    ModuleSP memory_module_sp;
192    // Use the memory module as the module if we have one...
193    if (address != LLDB_INVALID_ADDRESS)
194    {
195        FileSpec file_spec;
196        if (module_sp)
197            file_spec = module_sp->GetFileSpec();
198        else
199            file_spec.SetFile (name, false);
200
201        memory_module_sp = process->ReadModuleFromMemory (file_spec, address, false, false);
202        if (memory_module_sp && !uuid_is_valid)
203        {
204            uuid = memory_module_sp->GetUUID();
205            uuid_is_valid = uuid.IsValid();
206        }
207        if (memory_module_sp->GetObjectFile()
208            && memory_module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeExecutable
209            && memory_module_sp->GetObjectFile()->GetStrata() == ObjectFile::eStrataKernel)
210        {
211            memory_module_is_kernel = true;
212        }
213    }
214
215    if (!module_sp)
216    {
217        if (uuid_is_valid)
218        {
219            ModuleList &target_images = target.GetImages();
220            module_sp = target_images.FindModule(uuid);
221
222            if (!module_sp)
223            {
224                ModuleSpec module_spec;
225                module_spec.GetUUID() = uuid;
226                module_sp = target.GetSharedModule (module_spec);
227            }
228        }
229    }
230
231
232    if (memory_module_sp)
233    {
234        // Someone already supplied a file, make sure it is the right one.
235        if (module_sp)
236        {
237            if (module_sp->GetUUID() == memory_module_sp->GetUUID())
238            {
239                ObjectFile *ondisk_object_file = module_sp->GetObjectFile();
240                ObjectFile *memory_object_file = memory_module_sp->GetObjectFile();
241                if (memory_object_file && ondisk_object_file)
242                {
243                    SectionList *ondisk_section_list = ondisk_object_file->GetSectionList ();
244                    SectionList *memory_section_list = memory_object_file->GetSectionList ();
245                    if (memory_section_list && ondisk_section_list)
246                    {
247                        const uint32_t num_ondisk_sections = ondisk_section_list->GetSize();
248                        // There may be CTF sections in the memory image so we can't
249                        // always just compare the number of sections (which are actually
250                        // segments in mach-o parlance)
251                        uint32_t sect_idx = 0;
252
253
254                        // We now iterate through all sections in the file module
255                        // and look to see if the memory module has a load address
256                        // for that section.
257                        uint32_t num_sections_loaded = 0;
258                        for (sect_idx=0; sect_idx<num_ondisk_sections; ++sect_idx)
259                        {
260                            SectionSP ondisk_section_sp(ondisk_section_list->GetSectionAtIndex(sect_idx));
261                            if (ondisk_section_sp)
262                            {
263                                const Section *memory_section = memory_section_list->FindSectionByName(ondisk_section_sp->GetName()).get();
264                                if (memory_section)
265                                {
266                                    target.GetSectionLoadList().SetSectionLoadAddress (ondisk_section_sp, memory_section->GetFileAddress());
267                                    ++num_sections_loaded;
268                                }
269                            }
270                        }
271                        if (num_sections_loaded > 0)
272                            load_process_stop_id = process->GetStopID();
273                        else
274                            module_sp.reset(); // No sections were loaded
275                    }
276                    else
277                        module_sp.reset(); // One or both section lists
278                }
279                else
280                    module_sp.reset(); // One or both object files missing
281            }
282            else
283                module_sp.reset(); // UUID mismatch
284        }
285
286        // Try to locate the kext/kernel binary on the local filesystem, maybe with additional
287        // debug info/symbols still present, before we resort to copying it out of memory.
288        if (!module_sp)
289        {
290            ModuleSpec sym_spec;
291            sym_spec.GetUUID() = memory_module_sp->GetUUID();
292            if (Symbols::LocateExecutableObjectFile (sym_spec)
293                && sym_spec.GetArchitecture().IsValid()
294                && sym_spec.GetFileSpec().Exists())
295            {
296                module_sp = target.GetSharedModule (sym_spec);
297                if (module_sp.get ())
298                {
299                    target.SetExecutableModule(module_sp, false);
300                    if (address != LLDB_INVALID_ADDRESS
301                        && module_sp->GetObjectFile()
302                        && module_sp->GetObjectFile()->GetHeaderAddress().IsValid())
303                    {
304                        addr_t slide = address - module_sp->GetObjectFile()->GetHeaderAddress().GetFileAddress();
305                        bool changed = false;
306                        module_sp->SetLoadAddress (target, slide, changed);
307                        if (changed)
308                        {
309                            ModuleList modlist;
310                            modlist.Append (module_sp);
311                            target.ModulesDidLoad (modlist);
312                        }
313                        load_process_stop_id = process->GetStopID();
314                    }
315                }
316            }
317        }
318
319        // Use the memory module as the module if we didn't like the file
320        // module we either found or were supplied with
321        if (!module_sp)
322        {
323            module_sp = memory_module_sp;
324            // Load the memory image in the target as all addresses are already correct
325            bool changed = false;
326            target.GetImages().Append (memory_module_sp);
327            if (module_sp->SetLoadAddress (target, 0, changed))
328                load_process_stop_id = process->GetStopID();
329        }
330    }
331    bool is_loaded = IsLoaded();
332
333    if (so_address.IsValid())
334    {
335        if (is_loaded)
336            so_address.SetLoadAddress (address, &target);
337        else
338            target.GetImages().ResolveFileAddress (address, so_address);
339
340    }
341
342    if (is_loaded && module_sp && memory_module_is_kernel)
343    {
344        Stream *s = &target.GetDebugger().GetOutputStream();
345        if (s)
346        {
347            char uuidbuf[64];
348            s->Printf ("Kernel UUID: %s\n", module_sp->GetUUID().GetAsCString(uuidbuf, sizeof (uuidbuf)));
349            s->Printf ("Load Address: 0x%llx\n", address);
350            if (module_sp->GetFileSpec().GetDirectory().IsEmpty())
351            {
352                s->Printf ("Loaded kernel file %s\n", module_sp->GetFileSpec().GetFilename().AsCString());
353            }
354            else
355            {
356                s->Printf ("Loaded kernel file %s/%s\n",
357                              module_sp->GetFileSpec().GetDirectory().AsCString(),
358                              module_sp->GetFileSpec().GetFilename().AsCString());
359            }
360            s->Flush ();
361        }
362    }
363    return is_loaded;
364}
365
366uint32_t
367DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::GetAddressByteSize ()
368{
369    if (module_sp)
370        return module_sp->GetArchitecture().GetAddressByteSize();
371    return 0;
372}
373
374lldb::ByteOrder
375DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::GetByteOrder()
376{
377    if (module_sp)
378        return module_sp->GetArchitecture().GetByteOrder();
379    return lldb::endian::InlHostByteOrder();
380}
381
382lldb_private::ArchSpec
383DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::GetArchitecture () const
384{
385    if (module_sp)
386        return module_sp->GetArchitecture();
387    return lldb_private::ArchSpec ();
388}
389
390
391//----------------------------------------------------------------------
392// Load the kernel module and initialize the "m_kernel" member. Return
393// true _only_ if the kernel is loaded the first time through (subsequent
394// calls to this function should return false after the kernel has been
395// already loaded).
396//----------------------------------------------------------------------
397void
398DynamicLoaderDarwinKernel::LoadKernelModuleIfNeeded()
399{
400    if (!m_kext_summary_header_ptr_addr.IsValid())
401    {
402        m_kernel.Clear(false);
403        m_kernel.module_sp = m_process->GetTarget().GetExecutableModule();
404
405        ConstString kernel_name("mach_kernel");
406        if (m_kernel.module_sp.get()
407            && m_kernel.module_sp->GetObjectFile()
408            && !m_kernel.module_sp->GetObjectFile()->GetFileSpec().GetFilename().IsEmpty())
409        {
410            kernel_name = m_kernel.module_sp->GetObjectFile()->GetFileSpec().GetFilename();
411        }
412        strncpy (m_kernel.name, kernel_name.AsCString(), sizeof(m_kernel.name));
413        m_kernel.name[sizeof (m_kernel.name) - 1] = '\0';
414
415        if (m_kernel.address == LLDB_INVALID_ADDRESS)
416        {
417            m_kernel.address = m_process->GetImageInfoAddress ();
418            if (m_kernel.address == LLDB_INVALID_ADDRESS && m_kernel.module_sp)
419            {
420                // We didn't get a hint from the process, so we will
421                // try the kernel at the address that it exists at in
422                // the file if we have one
423                ObjectFile *kernel_object_file = m_kernel.module_sp->GetObjectFile();
424                if (kernel_object_file)
425                {
426                    addr_t load_address = kernel_object_file->GetHeaderAddress().GetLoadAddress(&m_process->GetTarget());
427                    addr_t file_address = kernel_object_file->GetHeaderAddress().GetFileAddress();
428                    if (load_address != LLDB_INVALID_ADDRESS && load_address != 0)
429                    {
430                        m_kernel.address = load_address;
431                        if (load_address != file_address)
432                        {
433                            // Don't accidentally relocate the kernel to the File address --
434                            // the Load address has already been set to its actual in-memory address.
435                            // Mark it as IsLoaded.
436                            m_kernel.load_process_stop_id = m_process->GetStopID();
437                        }
438                    }
439                    else
440                    {
441                        m_kernel.address = file_address;
442                    }
443                }
444            }
445        }
446
447        if (m_kernel.address != LLDB_INVALID_ADDRESS)
448        {
449            if (!m_kernel.LoadImageUsingMemoryModule (m_process))
450            {
451                m_kernel.LoadImageAtFileAddress (m_process);
452            }
453        }
454
455        if (m_kernel.IsLoaded())
456        {
457            static ConstString kext_summary_symbol ("gLoadedKextSummaries");
458            const Symbol *symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (kext_summary_symbol, eSymbolTypeData);
459            if (symbol)
460            {
461                m_kext_summary_header_ptr_addr = symbol->GetAddress();
462                // Update all image infos
463                ReadAllKextSummaries ();
464            }
465        }
466        else
467        {
468            m_kernel.Clear(false);
469        }
470    }
471}
472
473//----------------------------------------------------------------------
474// Static callback function that gets called when our DYLD notification
475// breakpoint gets hit. We update all of our image infos and then
476// let our super class DynamicLoader class decide if we should stop
477// or not (based on global preference).
478//----------------------------------------------------------------------
479bool
480DynamicLoaderDarwinKernel::BreakpointHitCallback (void *baton,
481                                                  StoppointCallbackContext *context,
482                                                  user_id_t break_id,
483                                                  user_id_t break_loc_id)
484{
485    return static_cast<DynamicLoaderDarwinKernel*>(baton)->BreakpointHit (context, break_id, break_loc_id);
486}
487
488bool
489DynamicLoaderDarwinKernel::BreakpointHit (StoppointCallbackContext *context,
490                                          user_id_t break_id,
491                                          user_id_t break_loc_id)
492{
493    LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
494    if (log)
495        log->Printf ("DynamicLoaderDarwinKernel::BreakpointHit (...)\n");
496
497    ReadAllKextSummaries ();
498
499    if (log)
500        PutToLog(log.get());
501
502    return GetStopWhenImagesChange();
503}
504
505
506bool
507DynamicLoaderDarwinKernel::ReadKextSummaryHeader ()
508{
509    Mutex::Locker locker(m_mutex);
510
511    // the all image infos is already valid for this process stop ID
512
513    m_kext_summaries.clear();
514    if (m_kext_summary_header_ptr_addr.IsValid())
515    {
516        const uint32_t addr_size = m_kernel.GetAddressByteSize ();
517        const ByteOrder byte_order = m_kernel.GetByteOrder();
518        Error error;
519        // Read enough bytes for a "OSKextLoadedKextSummaryHeader" structure
520        // which is currenty 4 uint32_t and a pointer.
521        uint8_t buf[24];
522        DataExtractor data (buf, sizeof(buf), byte_order, addr_size);
523        const size_t count = 4 * sizeof(uint32_t) + addr_size;
524        const bool prefer_file_cache = false;
525        if (m_process->GetTarget().ReadPointerFromMemory (m_kext_summary_header_ptr_addr,
526                                                          prefer_file_cache,
527                                                          error,
528                                                          m_kext_summary_header_addr))
529        {
530            // We got a valid address for our kext summary header and make sure it isn't NULL
531            if (m_kext_summary_header_addr.IsValid() &&
532                m_kext_summary_header_addr.GetFileAddress() != 0)
533            {
534                const size_t bytes_read = m_process->GetTarget().ReadMemory (m_kext_summary_header_addr, prefer_file_cache, buf, count, error);
535                if (bytes_read == count)
536                {
537                    uint32_t offset = 0;
538                    m_kext_summary_header.version = data.GetU32(&offset);
539                    if (m_kext_summary_header.version >= 2)
540                    {
541                        m_kext_summary_header.entry_size = data.GetU32(&offset);
542                    }
543                    else
544                    {
545                        // Versions less than 2 didn't have an entry size, it was hard coded
546                        m_kext_summary_header.entry_size = KERNEL_MODULE_ENTRY_SIZE_VERSION_1;
547                    }
548                    m_kext_summary_header.entry_count = data.GetU32(&offset);
549                    return true;
550                }
551            }
552        }
553    }
554    m_kext_summary_header_addr.Clear();
555    return false;
556}
557
558
559bool
560DynamicLoaderDarwinKernel::ParseKextSummaries (const Address &kext_summary_addr,
561                                               uint32_t count)
562{
563    OSKextLoadedKextSummary::collection kext_summaries;
564    LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
565    if (log)
566        log->Printf ("Adding %d modules.\n", count);
567
568    Mutex::Locker locker(m_mutex);
569
570    if (!ReadKextSummaries (kext_summary_addr, count, kext_summaries))
571        return false;
572
573    Stream *s = &m_process->GetTarget().GetDebugger().GetOutputStream();
574    if (s)
575        s->Printf ("Loading %d kext modules ", count);
576    for (uint32_t i = 0; i < count; i++)
577    {
578        if (!kext_summaries[i].LoadImageUsingMemoryModule (m_process))
579            kext_summaries[i].LoadImageAtFileAddress (m_process);
580
581        if (s)
582            s->Printf (".");
583
584        if (log)
585            kext_summaries[i].PutToLog (log.get());
586    }
587    if (s)
588    {
589        s->Printf (" done.\n");
590        s->Flush ();
591    }
592
593    bool return_value = AddModulesUsingImageInfos (kext_summaries);
594    return return_value;
595}
596
597// Adds the modules in image_infos to m_kext_summaries.
598// NB don't call this passing in m_kext_summaries.
599
600bool
601DynamicLoaderDarwinKernel::AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos)
602{
603    // Now add these images to the main list.
604    ModuleList loaded_module_list;
605
606    for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
607    {
608        OSKextLoadedKextSummary &image_info = image_infos[idx];
609        m_kext_summaries.push_back(image_info);
610
611        if (image_info.module_sp && m_process->GetStopID() == image_info.load_process_stop_id)
612            loaded_module_list.AppendIfNeeded (image_infos[idx].module_sp);
613    }
614
615    if (loaded_module_list.GetSize() > 0)
616    {
617        m_process->GetTarget().ModulesDidLoad (loaded_module_list);
618    }
619    return true;
620}
621
622
623uint32_t
624DynamicLoaderDarwinKernel::ReadKextSummaries (const Address &kext_summary_addr,
625                                              uint32_t image_infos_count,
626                                              OSKextLoadedKextSummary::collection &image_infos)
627{
628    const ByteOrder endian = m_kernel.GetByteOrder();
629    const uint32_t addr_size = m_kernel.GetAddressByteSize();
630
631    image_infos.resize(image_infos_count);
632    const size_t count = image_infos.size() * m_kext_summary_header.entry_size;
633    DataBufferHeap data(count, 0);
634    Error error;
635
636    const bool prefer_file_cache = false;
637    const size_t bytes_read = m_process->GetTarget().ReadMemory (kext_summary_addr,
638                                                                 prefer_file_cache,
639                                                                 data.GetBytes(),
640                                                                 data.GetByteSize(),
641                                                                 error);
642    if (bytes_read == count)
643    {
644
645        DataExtractor extractor (data.GetBytes(), data.GetByteSize(), endian, addr_size);
646        uint32_t i=0;
647        for (uint32_t kext_summary_offset = 0;
648             i < image_infos.size() && extractor.ValidOffsetForDataOfSize(kext_summary_offset, m_kext_summary_header.entry_size);
649             ++i, kext_summary_offset += m_kext_summary_header.entry_size)
650        {
651            uint32_t offset = kext_summary_offset;
652            const void *name_data = extractor.GetData(&offset, KERNEL_MODULE_MAX_NAME);
653            if (name_data == NULL)
654                break;
655            memcpy (image_infos[i].name, name_data, KERNEL_MODULE_MAX_NAME);
656            image_infos[i].uuid.SetBytes(extractor.GetData (&offset, 16));
657            image_infos[i].address          = extractor.GetU64(&offset);
658            if (!image_infos[i].so_address.SetLoadAddress (image_infos[i].address, &m_process->GetTarget()))
659                m_process->GetTarget().GetImages().ResolveFileAddress (image_infos[i].address, image_infos[i].so_address);
660            image_infos[i].size             = extractor.GetU64(&offset);
661            image_infos[i].version          = extractor.GetU64(&offset);
662            image_infos[i].load_tag         = extractor.GetU32(&offset);
663            image_infos[i].flags            = extractor.GetU32(&offset);
664            if ((offset - kext_summary_offset) < m_kext_summary_header.entry_size)
665            {
666                image_infos[i].reference_list = extractor.GetU64(&offset);
667            }
668            else
669            {
670                image_infos[i].reference_list = 0;
671            }
672//            printf ("[%3u] %*.*s: address=0x%16.16llx, size=0x%16.16llx, version=0x%16.16llx, load_tag=0x%8.8x, flags=0x%8.8x\n",
673//                    i,
674//                    KERNEL_MODULE_MAX_NAME, KERNEL_MODULE_MAX_NAME,  (char *)name_data,
675//                    image_infos[i].address,
676//                    image_infos[i].size,
677//                    image_infos[i].version,
678//                    image_infos[i].load_tag,
679//                    image_infos[i].flags);
680        }
681        if (i < image_infos.size())
682            image_infos.resize(i);
683    }
684    else
685    {
686        image_infos.clear();
687    }
688    return image_infos.size();
689}
690
691bool
692DynamicLoaderDarwinKernel::ReadAllKextSummaries ()
693{
694    LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
695
696    Mutex::Locker locker(m_mutex);
697
698    if (ReadKextSummaryHeader ())
699    {
700        if (m_kext_summary_header.entry_count > 0 && m_kext_summary_header_addr.IsValid())
701        {
702            Address summary_addr (m_kext_summary_header_addr);
703            summary_addr.Slide(m_kext_summary_header.GetSize());
704            if (!ParseKextSummaries (summary_addr, m_kext_summary_header.entry_count))
705            {
706                m_kext_summaries.clear();
707            }
708            return true;
709        }
710    }
711    return false;
712}
713
714//----------------------------------------------------------------------
715// Dump an image info structure to the file handle provided.
716//----------------------------------------------------------------------
717void
718DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::PutToLog (Log *log) const
719{
720    if (log == NULL)
721        return;
722    const uint8_t *u = (uint8_t *)uuid.GetBytes();
723
724    if (address == LLDB_INVALID_ADDRESS)
725    {
726        if (u)
727        {
728            log->Printf("\tuuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X name=\"%s\" (UNLOADED)",
729                        u[ 0], u[ 1], u[ 2], u[ 3],
730                        u[ 4], u[ 5], u[ 6], u[ 7],
731                        u[ 8], u[ 9], u[10], u[11],
732                        u[12], u[13], u[14], u[15],
733                        name);
734        }
735        else
736            log->Printf("\tname=\"%s\" (UNLOADED)", name);
737    }
738    else
739    {
740        if (u)
741        {
742            log->Printf("\taddr=0x%16.16llx size=0x%16.16llx version=0x%16.16llx load-tag=0x%8.8x flags=0x%8.8x ref-list=0x%16.16llx uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X name=\"%s\"",
743                        address, size, version, load_tag, flags, reference_list,
744                        u[ 0], u[ 1], u[ 2], u[ 3], u[ 4], u[ 5], u[ 6], u[ 7],
745                        u[ 8], u[ 9], u[10], u[11], u[12], u[13], u[14], u[15],
746                        name);
747        }
748        else
749        {
750            log->Printf("\t[0x%16.16llx - 0x%16.16llx) version=0x%16.16llx load-tag=0x%8.8x flags=0x%8.8x ref-list=0x%16.16llx name=\"%s\"",
751                        address, address+size, version, load_tag, flags, reference_list,
752                        name);
753        }
754    }
755}
756
757//----------------------------------------------------------------------
758// Dump the _dyld_all_image_infos members and all current image infos
759// that we have parsed to the file handle provided.
760//----------------------------------------------------------------------
761void
762DynamicLoaderDarwinKernel::PutToLog(Log *log) const
763{
764    if (log == NULL)
765        return;
766
767    Mutex::Locker locker(m_mutex);
768    log->Printf("gLoadedKextSummaries = 0x%16.16llx { version=%u, entry_size=%u, entry_count=%u }",
769                m_kext_summary_header_addr.GetFileAddress(),
770                m_kext_summary_header.version,
771                m_kext_summary_header.entry_size,
772                m_kext_summary_header.entry_count);
773
774    size_t i;
775    const size_t count = m_kext_summaries.size();
776    if (count > 0)
777    {
778        log->PutCString("Loaded:");
779        for (i = 0; i<count; i++)
780            m_kext_summaries[i].PutToLog(log);
781    }
782}
783
784void
785DynamicLoaderDarwinKernel::PrivateInitialize(Process *process)
786{
787    DEBUG_PRINTF("DynamicLoaderDarwinKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
788    Clear(true);
789    m_process = process;
790}
791
792void
793DynamicLoaderDarwinKernel::SetNotificationBreakpointIfNeeded ()
794{
795    if (m_break_id == LLDB_INVALID_BREAK_ID && m_kernel.module_sp)
796    {
797        DEBUG_PRINTF("DynamicLoaderDarwinKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
798
799
800        const bool internal_bp = true;
801        const LazyBool skip_prologue = eLazyBoolNo;
802        FileSpecList module_spec_list;
803        module_spec_list.Append (m_kernel.module_sp->GetFileSpec());
804        Breakpoint *bp = m_process->GetTarget().CreateBreakpoint (&module_spec_list,
805                                                                  NULL,
806                                                                  "OSKextLoadedKextSummariesUpdated",
807                                                                  eFunctionNameTypeFull,
808                                                                  skip_prologue,
809                                                                  internal_bp).get();
810
811        bp->SetCallback (DynamicLoaderDarwinKernel::BreakpointHitCallback, this, true);
812        m_break_id = bp->GetID();
813    }
814}
815
816//----------------------------------------------------------------------
817// Member function that gets called when the process state changes.
818//----------------------------------------------------------------------
819void
820DynamicLoaderDarwinKernel::PrivateProcessStateChanged (Process *process, StateType state)
821{
822    DEBUG_PRINTF("DynamicLoaderDarwinKernel::%s(%s)\n", __FUNCTION__, StateAsCString(state));
823    switch (state)
824    {
825    case eStateConnected:
826    case eStateAttaching:
827    case eStateLaunching:
828    case eStateInvalid:
829    case eStateUnloaded:
830    case eStateExited:
831    case eStateDetached:
832        Clear(false);
833        break;
834
835    case eStateStopped:
836        UpdateIfNeeded();
837        break;
838
839    case eStateRunning:
840    case eStateStepping:
841    case eStateCrashed:
842    case eStateSuspended:
843        break;
844
845    default:
846        break;
847    }
848}
849
850ThreadPlanSP
851DynamicLoaderDarwinKernel::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
852{
853    ThreadPlanSP thread_plan_sp;
854    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
855    if (log)
856        log->Printf ("Could not find symbol for step through.");
857    return thread_plan_sp;
858}
859
860Error
861DynamicLoaderDarwinKernel::CanLoadImage ()
862{
863    Error error;
864    error.SetErrorString("always unsafe to load or unload shared libraries in the darwin kernel");
865    return error;
866}
867
868void
869DynamicLoaderDarwinKernel::Initialize()
870{
871    PluginManager::RegisterPlugin (GetPluginNameStatic(),
872                                   GetPluginDescriptionStatic(),
873                                   CreateInstance);
874}
875
876void
877DynamicLoaderDarwinKernel::Terminate()
878{
879    PluginManager::UnregisterPlugin (CreateInstance);
880}
881
882
883const char *
884DynamicLoaderDarwinKernel::GetPluginNameStatic()
885{
886    return "dynamic-loader.macosx-kernel";
887}
888
889const char *
890DynamicLoaderDarwinKernel::GetPluginDescriptionStatic()
891{
892    return "Dynamic loader plug-in that watches for shared library loads/unloads in the MacOSX kernel.";
893}
894
895
896//------------------------------------------------------------------
897// PluginInterface protocol
898//------------------------------------------------------------------
899const char *
900DynamicLoaderDarwinKernel::GetPluginName()
901{
902    return "DynamicLoaderDarwinKernel";
903}
904
905const char *
906DynamicLoaderDarwinKernel::GetShortPluginName()
907{
908    return GetPluginNameStatic();
909}
910
911uint32_t
912DynamicLoaderDarwinKernel::GetPluginVersion()
913{
914    return 1;
915}
916
917lldb::ByteOrder
918DynamicLoaderDarwinKernel::GetByteOrderFromMagic (uint32_t magic)
919{
920    switch (magic)
921    {
922        case llvm::MachO::HeaderMagic32:
923        case llvm::MachO::HeaderMagic64:
924            return lldb::endian::InlHostByteOrder();
925
926        case llvm::MachO::HeaderMagic32Swapped:
927        case llvm::MachO::HeaderMagic64Swapped:
928            if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig)
929                return lldb::eByteOrderLittle;
930            else
931                return lldb::eByteOrderBig;
932
933        default:
934            break;
935    }
936    return lldb::eByteOrderInvalid;
937}
938
939