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