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 
34 using namespace lldb;
35 using namespace lldb_private;
36 
37 const char *
38 ProcessMachCore::GetPluginNameStatic()
39 {
40     return "mach-o-core";
41 }
42 
43 const char *
44 ProcessMachCore::GetPluginDescriptionStatic()
45 {
46     return "Mach-O core file debugging plug-in.";
47 }
48 
49 void
50 ProcessMachCore::Terminate()
51 {
52     PluginManager::UnregisterPlugin (ProcessMachCore::CreateInstance);
53 }
54 
55 
56 lldb::ProcessSP
57 ProcessMachCore::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 
65 bool
66 ProcessMachCore::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 //----------------------------------------------------------------------
98 ProcessMachCore::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 //----------------------------------------------------------------------
111 ProcessMachCore::~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 //----------------------------------------------------------------------
124 const char *
125 ProcessMachCore::GetPluginName()
126 {
127     return "Process debugging plug-in that loads mach-o core files.";
128 }
129 
130 const char *
131 ProcessMachCore::GetShortPluginName()
132 {
133     return GetPluginNameStatic();
134 }
135 
136 uint32_t
137 ProcessMachCore::GetPluginVersion()
138 {
139     return 1;
140 }
141 
142 bool
143 ProcessMachCore::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 //----------------------------------------------------------------------
200 Error
201 ProcessMachCore::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 
331 lldb_private::DynamicLoader *
332 ProcessMachCore::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 
339 bool
340 ProcessMachCore::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 
367 void
368 ProcessMachCore::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 
376 Error
377 ProcessMachCore::DoDestroy ()
378 {
379     return Error();
380 }
381 
382 //------------------------------------------------------------------
383 // Process Queries
384 //------------------------------------------------------------------
385 
386 bool
387 ProcessMachCore::IsAlive ()
388 {
389     return true;
390 }
391 
392 //------------------------------------------------------------------
393 // Process Memory
394 //------------------------------------------------------------------
395 size_t
396 ProcessMachCore::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 
403 size_t
404 ProcessMachCore::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 
428 void
429 ProcessMachCore::Clear()
430 {
431     m_thread_list.Clear();
432 }
433 
434 void
435 ProcessMachCore::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 
448 addr_t
449 ProcessMachCore::GetImageInfoAddress()
450 {
451     return m_dyld_addr;
452 }
453 
454 
455