1 //===-- DynamicLoaderDarwinKernel.h -----------------------------*- 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 #ifndef liblldb_DynamicLoaderDarwinKernel_h_ 11 #define liblldb_DynamicLoaderDarwinKernel_h_ 12 13 // C Includes 14 // C++ Includes 15 #include <map> 16 #include <vector> 17 #include <string> 18 19 // Other libraries and framework includes 20 #include "llvm/Support/MachO.h" 21 22 #include "lldb/Target/DynamicLoader.h" 23 #include "lldb/Host/FileSpec.h" 24 #include "lldb/Host/TimeValue.h" 25 #include "lldb/Core/UUID.h" 26 #include "lldb/Host/Mutex.h" 27 #include "lldb/Target/Process.h" 28 29 class DynamicLoaderDarwinKernel : public lldb_private::DynamicLoader 30 { 31 public: 32 //------------------------------------------------------------------ 33 // Static Functions 34 //------------------------------------------------------------------ 35 static void 36 Initialize(); 37 38 static void 39 Terminate(); 40 41 static const char * 42 GetPluginNameStatic(); 43 44 static const char * 45 GetPluginDescriptionStatic(); 46 47 static lldb_private::DynamicLoader * 48 CreateInstance (lldb_private::Process *process, bool force); 49 50 DynamicLoaderDarwinKernel (lldb_private::Process *process); 51 52 virtual 53 ~DynamicLoaderDarwinKernel (); 54 //------------------------------------------------------------------ 55 /// Called after attaching a process. 56 /// 57 /// Allow DynamicLoader plug-ins to execute some code after 58 /// attaching to a process. 59 //------------------------------------------------------------------ 60 virtual void 61 DidAttach (); 62 63 virtual void 64 DidLaunch (); 65 66 virtual lldb::ThreadPlanSP 67 GetStepThroughTrampolinePlan (lldb_private::Thread &thread, 68 bool stop_others); 69 70 virtual lldb_private::Error 71 CanLoadImage (); 72 73 //------------------------------------------------------------------ 74 // PluginInterface protocol 75 //------------------------------------------------------------------ 76 virtual const char * 77 GetPluginName(); 78 79 virtual const char * 80 GetShortPluginName(); 81 82 virtual uint32_t 83 GetPluginVersion(); 84 85 protected: 86 void 87 PrivateInitialize (lldb_private::Process *process); 88 89 void 90 PrivateProcessStateChanged (lldb_private::Process *process, 91 lldb::StateType state); 92 93 void 94 UpdateIfNeeded(); 95 96 void 97 LoadKernelModuleIfNeeded (); 98 99 void 100 Clear (bool clear_process); 101 102 void 103 PutToLog (lldb_private::Log *log) const; 104 105 static bool 106 BreakpointHitCallback (void *baton, 107 lldb_private::StoppointCallbackContext *context, 108 lldb::user_id_t break_id, 109 lldb::user_id_t break_loc_id); 110 111 bool 112 BreakpointHit (lldb_private::StoppointCallbackContext *context, 113 lldb::user_id_t break_id, 114 lldb::user_id_t break_loc_id); 115 uint32_t 116 GetAddrByteSize() 117 { 118 return m_kernel.GetAddressByteSize(); 119 } 120 121 static lldb::ByteOrder 122 GetByteOrderFromMagic (uint32_t magic) 123 { 124 switch (magic) 125 { 126 case llvm::MachO::HeaderMagic32: 127 case llvm::MachO::HeaderMagic64: 128 return lldb::endian::InlHostByteOrder(); 129 130 case llvm::MachO::HeaderMagic32Swapped: 131 case llvm::MachO::HeaderMagic64Swapped: 132 if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig) 133 return lldb::eByteOrderLittle; 134 else 135 return lldb::eByteOrderBig; 136 137 default: 138 break; 139 } 140 return lldb::eByteOrderInvalid; 141 } 142 enum 143 { 144 KERNEL_MODULE_MAX_NAME = 64u, 145 // Versions less than 2 didn't have an entry size, 146 // they had a 64 bit name, 16 byte UUID, 8 byte addr, 147 // 8 byte size, 8 byte version, 4 byte load tag, and 148 // 4 byte flags 149 KERNEL_MODULE_ENTRY_SIZE_VERSION_1 = 64u + 16u + 8u + 8u + 8u + 4u + 4u 150 }; 151 152 struct OSKextLoadedKextSummary 153 { 154 char name[KERNEL_MODULE_MAX_NAME]; 155 lldb::ModuleSP module_sp; 156 uint32_t load_process_stop_id; 157 lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros 158 lldb_private::Address so_address; // The section offset address for this kext in case it can be read from object files 159 uint64_t address; 160 uint64_t size; 161 uint64_t version; 162 uint32_t load_tag; 163 uint32_t flags; 164 uint64_t reference_list; 165 166 OSKextLoadedKextSummary() : 167 module_sp (), 168 load_process_stop_id (UINT32_MAX), 169 uuid (), 170 so_address (), 171 address (LLDB_INVALID_ADDRESS), 172 size (0), 173 version (0), 174 load_tag (0), 175 flags (0), 176 reference_list (0) 177 { 178 name[0] = '\0'; 179 } 180 181 bool 182 IsLoaded () 183 { 184 return load_process_stop_id != UINT32_MAX; 185 } 186 187 void 188 Clear (bool load_cmd_data_only) 189 { 190 if (!load_cmd_data_only) 191 { 192 so_address.Clear(); 193 address = LLDB_INVALID_ADDRESS; 194 size = 0; 195 version = 0; 196 load_tag = 0; 197 flags = 0; 198 reference_list = 0; 199 name[0] = '\0'; 200 } 201 module_sp.reset(); 202 load_process_stop_id = UINT32_MAX; 203 } 204 205 bool 206 LoadImageUsingMemoryModule (lldb_private::Process *process); 207 208 // bool 209 // operator == (const OSKextLoadedKextSummary& rhs) const 210 // { 211 // return address == rhs.address 212 // && size == rhs.size 213 // //&& module_sp.get() == rhs.module_sp.get() 214 // && uuid == rhs.uuid 215 // && version == rhs.version 216 // && load_tag == rhs.load_tag 217 // && flags == rhs.flags 218 // && reference_list == rhs.reference_list 219 // && strncmp (name, rhs.name, KERNEL_MODULE_MAX_NAME) == 0; 220 // } 221 // 222 bool 223 UUIDValid() const 224 { 225 return uuid.IsValid(); 226 } 227 228 uint32_t 229 GetAddressByteSize () 230 { 231 if (module_sp) 232 return module_sp->GetArchitecture().GetAddressByteSize(); 233 return 0; 234 } 235 236 lldb::ByteOrder 237 GetByteOrder() 238 { 239 if (module_sp) 240 return module_sp->GetArchitecture().GetByteOrder(); 241 return lldb::endian::InlHostByteOrder(); 242 } 243 244 lldb_private::ArchSpec 245 GetArchitecture () const 246 { 247 if (module_sp) 248 return module_sp->GetArchitecture(); 249 return lldb_private::ArchSpec (); 250 } 251 252 void 253 PutToLog (lldb_private::Log *log) const; 254 255 typedef std::vector<OSKextLoadedKextSummary> collection; 256 typedef collection::iterator iterator; 257 typedef collection::const_iterator const_iterator; 258 }; 259 260 struct OSKextLoadedKextSummaryHeader 261 { 262 uint32_t version; 263 uint32_t entry_size; 264 uint32_t entry_count; 265 lldb::addr_t image_infos_addr; 266 267 OSKextLoadedKextSummaryHeader() : 268 version (0), 269 entry_size (0), 270 entry_count (0), 271 image_infos_addr (LLDB_INVALID_ADDRESS) 272 { 273 } 274 275 uint32_t 276 GetSize() 277 { 278 switch (version) 279 { 280 case 0: return 0; // Can't know the size without a valid version 281 case 1: return 8; // Version 1 only had a version + entry_count 282 default: break; 283 } 284 // Version 2 and above has version, entry_size, entry_count, and reserved 285 return 16; 286 } 287 288 void 289 Clear() 290 { 291 version = 0; 292 entry_size = 0; 293 entry_count = 0; 294 image_infos_addr = LLDB_INVALID_ADDRESS; 295 } 296 297 bool 298 IsValid() const 299 { 300 return version >= 1 || version <= 2; 301 } 302 }; 303 304 void 305 RegisterNotificationCallbacks(); 306 307 void 308 UnregisterNotificationCallbacks(); 309 310 void 311 SetNotificationBreakpointIfNeeded (); 312 313 bool 314 ReadAllKextSummaries (); 315 316 bool 317 ReadKextSummaryHeader (); 318 319 bool 320 ParseKextSummaries (const lldb_private::Address &kext_summary_addr, 321 uint32_t count); 322 323 bool 324 AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos); 325 326 void 327 UpdateImageInfosHeaderAndLoadCommands(OSKextLoadedKextSummary::collection &image_infos, 328 uint32_t infos_count, 329 bool update_executable); 330 331 uint32_t 332 ReadKextSummaries (const lldb_private::Address &kext_summary_addr, 333 uint32_t image_infos_count, 334 OSKextLoadedKextSummary::collection &image_infos); 335 336 OSKextLoadedKextSummary m_kernel; // Info about the current kernel image being used 337 lldb_private::Address m_kext_summary_header_ptr_addr; 338 lldb_private::Address m_kext_summary_header_addr; 339 OSKextLoadedKextSummaryHeader m_kext_summary_header; 340 OSKextLoadedKextSummary::collection m_kext_summaries; 341 mutable lldb_private::Mutex m_mutex; 342 lldb::user_id_t m_break_id; 343 344 private: 345 DISALLOW_COPY_AND_ASSIGN (DynamicLoaderDarwinKernel); 346 }; 347 348 #endif // liblldb_DynamicLoaderDarwinKernel_h_ 349