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 
17 // Other libraries and framework includes
18 #include "lldb/Core/Debugger.h"
19 #include "lldb/Core/PluginManager.h"
20 #include "lldb/Core/State.h"
21 #include "lldb/Host/Host.h"
22 #include "lldb/Target/Target.h"
23 #include "lldb/Target/Thread.h"
24 
25 // Project includes
26 #include "ProcessMachCore.h"
27 #include "ThreadMachCore.h"
28 #include "StopInfoMachException.h"
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
33 const char *
34 ProcessMachCore::GetPluginNameStatic()
35 {
36     return "mach-o-core";
37 }
38 
39 const char *
40 ProcessMachCore::GetPluginDescriptionStatic()
41 {
42     return "Mach-O core file debugging plug-in.";
43 }
44 
45 void
46 ProcessMachCore::Terminate()
47 {
48     PluginManager::UnregisterPlugin (ProcessMachCore::CreateInstance);
49 }
50 
51 
52 lldb::ProcessSP
53 ProcessMachCore::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file)
54 {
55     lldb::ProcessSP process_sp;
56     if (crash_file)
57         process_sp.reset(new ProcessMachCore (target, listener, *crash_file));
58     return process_sp;
59 }
60 
61 bool
62 ProcessMachCore::CanDebug(Target &target, bool plugin_specified_by_name)
63 {
64     if (plugin_specified_by_name)
65         return true;
66 
67     // For now we are just making sure the file exists for a given module
68     if (!m_core_module_sp && m_core_file.Exists())
69     {
70         Error error (ModuleList::GetSharedModule(m_core_file, target.GetArchitecture(), NULL, NULL, 0, m_core_module_sp, NULL, NULL));
71 
72         if (m_core_module_sp)
73         {
74             const llvm::Triple &triple_ref = m_core_module_sp->GetArchitecture().GetTriple();
75             if (triple_ref.getOS() == llvm::Triple::Darwin &&
76                 triple_ref.getVendor() == llvm::Triple::Apple)
77             {
78                 ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
79                 if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile)
80                     return true;
81             }
82         }
83     }
84     return false;
85 }
86 
87 //----------------------------------------------------------------------
88 // ProcessMachCore constructor
89 //----------------------------------------------------------------------
90 ProcessMachCore::ProcessMachCore(Target& target, Listener &listener, const FileSpec &core_file) :
91     Process (target, listener),
92     m_core_aranges (),
93     m_core_module_sp (),
94     m_core_file (core_file),
95     m_shlib_addr (LLDB_INVALID_ADDRESS)
96 {
97 }
98 
99 //----------------------------------------------------------------------
100 // Destructor
101 //----------------------------------------------------------------------
102 ProcessMachCore::~ProcessMachCore()
103 {
104     Clear();
105     // We need to call finalize on the process before destroying ourselves
106     // to make sure all of the broadcaster cleanup goes as planned. If we
107     // destruct this class, then Process::~Process() might have problems
108     // trying to fully destroy the broadcaster.
109     Finalize();
110 }
111 
112 //----------------------------------------------------------------------
113 // PluginInterface
114 //----------------------------------------------------------------------
115 const char *
116 ProcessMachCore::GetPluginName()
117 {
118     return "Process debugging plug-in that loads mach-o core files.";
119 }
120 
121 const char *
122 ProcessMachCore::GetShortPluginName()
123 {
124     return GetPluginNameStatic();
125 }
126 
127 uint32_t
128 ProcessMachCore::GetPluginVersion()
129 {
130     return 1;
131 }
132 
133 //----------------------------------------------------------------------
134 // Process Control
135 //----------------------------------------------------------------------
136 Error
137 ProcessMachCore::DoLoadCore ()
138 {
139     Error error;
140     DataExtractor data;
141     ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
142     if (core_objfile == NULL)
143     {
144         error.SetErrorString ("invalid core object file");
145         return error;
146     }
147     SectionList *section_list = core_objfile->GetSectionList();
148     if (section_list == NULL)
149     {
150         error.SetErrorString ("core file has no sections");
151         return error;
152     }
153 
154     const uint32_t num_sections = section_list->GetNumSections(0);
155     if (num_sections == 0)
156     {
157         error.SetErrorString ("core file has no sections");
158         return error;
159     }
160     bool ranges_are_sorted = true;
161     addr_t vm_addr = 0;
162     for (uint32_t i=0; i<num_sections; ++i)
163     {
164         Section *section = section_list->GetSectionAtIndex (i).get();
165         if (section)
166         {
167             lldb::addr_t section_vm_addr = section->GetFileAddress();
168 
169             if (m_shlib_addr == LLDB_INVALID_ADDRESS)
170             {
171                 if (core_objfile->ReadSectionData (section, data))
172                 {
173                     uint32_t offset = 0;
174                     llvm::MachO::mach_header header;
175                     if (data.GetU32(&offset, &header, sizeof(header)/sizeof(uint32_t)))
176                     {
177 
178                         if (header.magic == llvm::MachO::HeaderMagic32 ||
179                             header.magic == llvm::MachO::HeaderMagic64)
180                         {
181                             // Check MH_EXECUTABLE to see if we can find the mach image
182                             // that contains the shared library list. The dynamic loader
183                             // (dyld) is what contains the list for user applications,
184                             // and the mach kernel contains a global that has the list
185                             // of kexts to load
186                             switch (header.filetype)
187                             {
188                             case llvm::MachO::HeaderFileTypeDynamicLinkEditor:
189                                 // Address of dyld "struct mach_header" in the core file
190                                 m_shlib_addr = section_vm_addr;
191                                 break;
192                             case llvm::MachO::HeaderFileTypeExecutable:
193                                 // Check MH_EXECUTABLE file types to see if the dynamic link object flag
194                                 // is NOT set. If it isn't, then we have a mach_kernel.
195                                 if ((header.flags & llvm::MachO::HeaderFlagBitIsDynamicLinkObject) == 0)
196                                 {
197                                     // Address of the mach kernel "struct mach_header" in the core file.
198                                     m_shlib_addr = section_vm_addr;
199                                 }
200                                 break;
201                             }
202                         }
203                     }
204                 }
205             }
206             FileRange file_range (section->GetFileOffset(), section->GetFileSize());
207             VMRangeToFileOffset::Entry range_entry (section_vm_addr,
208                                                     section->GetByteSize(),
209                                                     file_range);
210 
211             if (vm_addr > section_vm_addr)
212                 ranges_are_sorted = false;
213             vm_addr = section->GetFileAddress();
214             VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
215             if (last_entry &&
216                 last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
217                 last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase())
218             {
219                 last_entry->SetRangeEnd (range_entry.GetRangeEnd());
220                 last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd());
221             }
222             else
223             {
224                 m_core_aranges.Append(range_entry);
225             }
226         }
227     }
228     if (!ranges_are_sorted)
229     {
230         m_core_aranges.Sort();
231     }
232     if (!m_target.GetArchitecture().IsValid())
233         m_target.SetArchitecture(m_core_module_sp->GetArchitecture());
234 
235     return error;
236 }
237 
238 
239 uint32_t
240 ProcessMachCore::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
241 {
242     if (old_thread_list.GetSize(false) == 0)
243     {
244         // Make up the thread the first time this is called so we can setup our one and only
245         // core thread state.
246         ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
247 
248         if (core_objfile)
249         {
250             const uint32_t num_threads = core_objfile->GetNumThreadContexts ();
251             for (lldb::tid_t tid = 0; tid < num_threads; ++tid)
252             {
253                 ThreadSP thread_sp(new ThreadMachCore (*this, tid));
254                 new_thread_list.AddThread (thread_sp);
255             }
256         }
257     }
258     else
259     {
260         const uint32_t num_threads = old_thread_list.GetSize(false);
261         for (uint32_t i=0; i<num_threads; ++i)
262             new_thread_list.AddThread (old_thread_list.GetThreadAtIndex (i));
263     }
264     return new_thread_list.GetSize(false);
265 }
266 
267 void
268 ProcessMachCore::RefreshStateAfterStop ()
269 {
270     // Let all threads recover from stopping and do any clean up based
271     // on the previous thread state (if any).
272     m_thread_list.RefreshStateAfterStop();
273     //SetThreadStopInfo (m_last_stop_packet);
274 }
275 
276 Error
277 ProcessMachCore::DoDestroy ()
278 {
279     return Error();
280 }
281 
282 //------------------------------------------------------------------
283 // Process Queries
284 //------------------------------------------------------------------
285 
286 bool
287 ProcessMachCore::IsAlive ()
288 {
289     return true;
290 }
291 
292 //------------------------------------------------------------------
293 // Process Memory
294 //------------------------------------------------------------------
295 size_t
296 ProcessMachCore::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
297 {
298     ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
299 
300     if (core_objfile)
301     {
302         const VMRangeToFileOffset::Entry *core_memory_entry = m_core_aranges.FindEntryThatContains (addr);
303         if (core_memory_entry)
304         {
305             const addr_t offset = addr - core_memory_entry->GetRangeBase();
306             const addr_t bytes_left = core_memory_entry->GetRangeEnd() - addr;
307             size_t bytes_to_read = size;
308             if (bytes_to_read > bytes_left)
309                 bytes_to_read = bytes_left;
310             return core_objfile->CopyData (core_memory_entry->data.GetRangeBase() + offset, bytes_to_read, buf);
311         }
312         else
313         {
314             error.SetErrorStringWithFormat ("core file does not contain 0x%llx", addr);
315         }
316     }
317     return 0;
318 }
319 
320 void
321 ProcessMachCore::Clear()
322 {
323     m_thread_list.Clear();
324 }
325 
326 void
327 ProcessMachCore::Initialize()
328 {
329     static bool g_initialized = false;
330 
331     if (g_initialized == false)
332     {
333         g_initialized = true;
334         PluginManager::RegisterPlugin (GetPluginNameStatic(),
335                                        GetPluginDescriptionStatic(),
336                                        CreateInstance);
337     }
338 }
339 
340 addr_t
341 ProcessMachCore::GetImageInfoAddress()
342 {
343     return m_shlib_addr;
344 }
345 
346 
347