1 //===-- ProcessMinidump.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 // Project includes 11 #include "ProcessMinidump.h" 12 #include "ThreadMinidump.h" 13 14 // Other libraries and framework includes 15 #include "lldb/Core/Module.h" 16 #include "lldb/Core/ModuleSpec.h" 17 #include "lldb/Core/PluginManager.h" 18 #include "lldb/Core/Section.h" 19 #include "lldb/Target/DynamicLoader.h" 20 #include "lldb/Target/MemoryRegionInfo.h" 21 #include "lldb/Target/SectionLoadList.h" 22 #include "lldb/Target/Target.h" 23 #include "lldb/Target/UnixSignals.h" 24 #include "lldb/Utility/DataBufferLLVM.h" 25 #include "lldb/Utility/LLDBAssert.h" 26 #include "lldb/Utility/Log.h" 27 #include "lldb/Utility/State.h" 28 29 #include "llvm/Support/MemoryBuffer.h" 30 #include "llvm/Support/Threading.h" 31 32 #include "Plugins/Process/Utility/StopInfoMachException.h" 33 // C includes 34 // C++ includes 35 36 using namespace lldb; 37 using namespace lldb_private; 38 using namespace minidump; 39 40 //------------------------------------------------------------------ 41 /// A placeholder module used for minidumps, where the original 42 /// object files may not be available (so we can't parse the object 43 /// files to extract the set of sections/segments) 44 /// 45 /// This placeholder module has a single synthetic section (.module_image) 46 /// which represents the module memory range covering the whole module. 47 //------------------------------------------------------------------ 48 class PlaceholderModule : public Module { 49 public: 50 PlaceholderModule(const ModuleSpec &module_spec) : 51 Module(module_spec.GetFileSpec(), module_spec.GetArchitecture()) { 52 if (module_spec.GetUUID().IsValid()) 53 SetUUID(module_spec.GetUUID()); 54 } 55 56 // Creates a synthetic module section covering the whole module image (and 57 // sets the section load address as well) 58 void CreateImageSection(const MinidumpModule *module, Target& target) { 59 const ConstString section_name(".module_image"); 60 lldb::SectionSP section_sp(new Section( 61 shared_from_this(), // Module to which this section belongs. 62 nullptr, // ObjectFile 63 0, // Section ID. 64 section_name, // Section name. 65 eSectionTypeContainer, // Section type. 66 module->base_of_image, // VM address. 67 module->size_of_image, // VM size in bytes of this section. 68 0, // Offset of this section in the file. 69 module->size_of_image, // Size of the section as found in the file. 70 12, // Alignment of the section (log2) 71 0, // Flags for this section. 72 1)); // Number of host bytes per target byte 73 section_sp->SetPermissions(ePermissionsExecutable | ePermissionsReadable); 74 GetSectionList()->AddSection(section_sp); 75 target.GetSectionLoadList().SetSectionLoadAddress( 76 section_sp, module->base_of_image); 77 } 78 79 ObjectFile *GetObjectFile() override { return nullptr; } 80 81 SectionList *GetSectionList() override { 82 return Module::GetUnifiedSectionList(); 83 } 84 }; 85 86 ConstString ProcessMinidump::GetPluginNameStatic() { 87 static ConstString g_name("minidump"); 88 return g_name; 89 } 90 91 const char *ProcessMinidump::GetPluginDescriptionStatic() { 92 return "Minidump plug-in."; 93 } 94 95 lldb::ProcessSP ProcessMinidump::CreateInstance(lldb::TargetSP target_sp, 96 lldb::ListenerSP listener_sp, 97 const FileSpec *crash_file) { 98 if (!crash_file) 99 return nullptr; 100 101 lldb::ProcessSP process_sp; 102 // Read enough data for the Minidump header 103 constexpr size_t header_size = sizeof(MinidumpHeader); 104 auto DataPtr = 105 DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(), header_size, 0); 106 if (!DataPtr) 107 return nullptr; 108 109 lldbassert(DataPtr->GetByteSize() == header_size); 110 111 // first, only try to parse the header, beacuse we need to be fast 112 llvm::ArrayRef<uint8_t> HeaderBytes = DataPtr->GetData(); 113 const MinidumpHeader *header = MinidumpHeader::Parse(HeaderBytes); 114 if (header == nullptr) 115 return nullptr; 116 117 auto AllData = DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(), -1, 0); 118 if (!AllData) 119 return nullptr; 120 121 auto minidump_parser = MinidumpParser::Create(AllData); 122 // check if the parser object is valid 123 if (!minidump_parser) 124 return nullptr; 125 126 return std::make_shared<ProcessMinidump>(target_sp, listener_sp, *crash_file, 127 minidump_parser.getValue()); 128 } 129 130 bool ProcessMinidump::CanDebug(lldb::TargetSP target_sp, 131 bool plugin_specified_by_name) { 132 return true; 133 } 134 135 ProcessMinidump::ProcessMinidump(lldb::TargetSP target_sp, 136 lldb::ListenerSP listener_sp, 137 const FileSpec &core_file, 138 MinidumpParser minidump_parser) 139 : Process(target_sp, listener_sp), m_minidump_parser(minidump_parser), 140 m_core_file(core_file), m_is_wow64(false) {} 141 142 ProcessMinidump::~ProcessMinidump() { 143 Clear(); 144 // We need to call finalize on the process before destroying ourselves to 145 // make sure all of the broadcaster cleanup goes as planned. If we destruct 146 // this class, then Process::~Process() might have problems trying to fully 147 // destroy the broadcaster. 148 Finalize(); 149 } 150 151 void ProcessMinidump::Initialize() { 152 static llvm::once_flag g_once_flag; 153 154 llvm::call_once(g_once_flag, []() { 155 PluginManager::RegisterPlugin(GetPluginNameStatic(), 156 GetPluginDescriptionStatic(), 157 ProcessMinidump::CreateInstance); 158 }); 159 } 160 161 void ProcessMinidump::Terminate() { 162 PluginManager::UnregisterPlugin(ProcessMinidump::CreateInstance); 163 } 164 165 Status ProcessMinidump::DoLoadCore() { 166 Status error; 167 168 // Minidump parser initialization & consistency checks 169 error = m_minidump_parser.Initialize(); 170 if (error.Fail()) 171 return error; 172 173 // Do we support the minidump's architecture? 174 ArchSpec arch = GetArchitecture(); 175 switch (arch.GetMachine()) { 176 case llvm::Triple::x86: 177 case llvm::Triple::x86_64: 178 case llvm::Triple::arm: 179 case llvm::Triple::aarch64: 180 // Any supported architectures must be listed here and also supported in 181 // ThreadMinidump::CreateRegisterContextForFrame(). 182 break; 183 default: 184 error.SetErrorStringWithFormat("unsupported minidump architecture: %s", 185 arch.GetArchitectureName()); 186 return error; 187 } 188 GetTarget().SetArchitecture(arch, true /*set_platform*/); 189 190 m_thread_list = m_minidump_parser.GetThreads(); 191 m_active_exception = m_minidump_parser.GetExceptionStream(); 192 ReadModuleList(); 193 194 llvm::Optional<lldb::pid_t> pid = m_minidump_parser.GetPid(); 195 if (!pid) { 196 error.SetErrorString("failed to parse PID"); 197 return error; 198 } 199 SetID(pid.getValue()); 200 201 return error; 202 } 203 204 DynamicLoader *ProcessMinidump::GetDynamicLoader() { 205 if (m_dyld_ap.get() == nullptr) 206 m_dyld_ap.reset(DynamicLoader::FindPlugin(this, nullptr)); 207 return m_dyld_ap.get(); 208 } 209 210 ConstString ProcessMinidump::GetPluginName() { return GetPluginNameStatic(); } 211 212 uint32_t ProcessMinidump::GetPluginVersion() { return 1; } 213 214 Status ProcessMinidump::DoDestroy() { return Status(); } 215 216 void ProcessMinidump::RefreshStateAfterStop() { 217 if (!m_active_exception) 218 return; 219 220 if (m_active_exception->exception_record.exception_code == 221 MinidumpException::DumpRequested) { 222 return; 223 } 224 225 lldb::StopInfoSP stop_info; 226 lldb::ThreadSP stop_thread; 227 228 Process::m_thread_list.SetSelectedThreadByID(m_active_exception->thread_id); 229 stop_thread = Process::m_thread_list.GetSelectedThread(); 230 ArchSpec arch = GetArchitecture(); 231 232 if (arch.GetTriple().getOS() == llvm::Triple::Linux) { 233 stop_info = StopInfo::CreateStopReasonWithSignal( 234 *stop_thread, m_active_exception->exception_record.exception_code); 235 } else if (arch.GetTriple().getVendor() == llvm::Triple::Apple) { 236 stop_info = StopInfoMachException::CreateStopReasonWithMachException( 237 *stop_thread, m_active_exception->exception_record.exception_code, 2, 238 m_active_exception->exception_record.exception_flags, 239 m_active_exception->exception_record.exception_address, 0); 240 } else { 241 std::string desc; 242 llvm::raw_string_ostream desc_stream(desc); 243 desc_stream << "Exception " 244 << llvm::format_hex( 245 m_active_exception->exception_record.exception_code, 8) 246 << " encountered at address " 247 << llvm::format_hex( 248 m_active_exception->exception_record.exception_address, 249 8); 250 stop_info = StopInfo::CreateStopReasonWithException( 251 *stop_thread, desc_stream.str().c_str()); 252 } 253 254 stop_thread->SetStopInfo(stop_info); 255 } 256 257 bool ProcessMinidump::IsAlive() { return true; } 258 259 bool ProcessMinidump::WarnBeforeDetach() const { return false; } 260 261 size_t ProcessMinidump::ReadMemory(lldb::addr_t addr, void *buf, size_t size, 262 Status &error) { 263 // Don't allow the caching that lldb_private::Process::ReadMemory does since 264 // we have it all cached in our dump file anyway. 265 return DoReadMemory(addr, buf, size, error); 266 } 267 268 size_t ProcessMinidump::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, 269 Status &error) { 270 271 llvm::ArrayRef<uint8_t> mem = m_minidump_parser.GetMemory(addr, size); 272 if (mem.empty()) { 273 error.SetErrorString("could not parse memory info"); 274 return 0; 275 } 276 277 std::memcpy(buf, mem.data(), mem.size()); 278 return mem.size(); 279 } 280 281 ArchSpec ProcessMinidump::GetArchitecture() { 282 if (!m_is_wow64) { 283 return m_minidump_parser.GetArchitecture(); 284 } 285 286 llvm::Triple triple; 287 triple.setVendor(llvm::Triple::VendorType::UnknownVendor); 288 triple.setArch(llvm::Triple::ArchType::x86); 289 triple.setOS(llvm::Triple::OSType::Win32); 290 return ArchSpec(triple); 291 } 292 293 Status ProcessMinidump::GetMemoryRegionInfo(lldb::addr_t load_addr, 294 MemoryRegionInfo &range_info) { 295 Status error; 296 auto info = m_minidump_parser.GetMemoryRegionInfo(load_addr); 297 if (!info) { 298 error.SetErrorString("No valid MemoryRegionInfo found!"); 299 return error; 300 } 301 range_info = info.getValue(); 302 return error; 303 } 304 305 void ProcessMinidump::Clear() { Process::m_thread_list.Clear(); } 306 307 bool ProcessMinidump::UpdateThreadList(ThreadList &old_thread_list, 308 ThreadList &new_thread_list) { 309 uint32_t num_threads = 0; 310 if (m_thread_list.size() > 0) 311 num_threads = m_thread_list.size(); 312 313 for (lldb::tid_t tid = 0; tid < num_threads; ++tid) { 314 llvm::ArrayRef<uint8_t> context; 315 if (!m_is_wow64) 316 context = m_minidump_parser.GetThreadContext(m_thread_list[tid]); 317 else 318 context = m_minidump_parser.GetThreadContextWow64(m_thread_list[tid]); 319 320 lldb::ThreadSP thread_sp( 321 new ThreadMinidump(*this, m_thread_list[tid], context)); 322 new_thread_list.AddThread(thread_sp); 323 } 324 return new_thread_list.GetSize(false) > 0; 325 } 326 327 void ProcessMinidump::ReadModuleList() { 328 std::vector<const MinidumpModule *> filtered_modules = 329 m_minidump_parser.GetFilteredModuleList(); 330 331 for (auto module : filtered_modules) { 332 llvm::Optional<std::string> name = 333 m_minidump_parser.GetMinidumpString(module->module_name_rva); 334 335 if (!name) 336 continue; 337 338 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES)); 339 if (log) { 340 log->Printf("ProcessMinidump::%s found module: name: %s %#010" PRIx64 341 "-%#010" PRIx64 " size: %" PRIu32, 342 __FUNCTION__, name.getValue().c_str(), 343 uint64_t(module->base_of_image), 344 module->base_of_image + module->size_of_image, 345 uint32_t(module->size_of_image)); 346 } 347 348 // check if the process is wow64 - a 32 bit windows process running on a 349 // 64 bit windows 350 if (llvm::StringRef(name.getValue()).endswith_lower("wow64.dll")) { 351 m_is_wow64 = true; 352 } 353 354 const auto uuid = m_minidump_parser.GetModuleUUID(module); 355 const auto file_spec = 356 FileSpec(name.getValue(), true, GetArchitecture().GetTriple()); 357 ModuleSpec module_spec(file_spec, uuid); 358 Status error; 359 lldb::ModuleSP module_sp = GetTarget().GetSharedModule(module_spec, &error); 360 if (!module_sp || error.Fail()) { 361 // We failed to locate a matching local object file. Fortunately, the 362 // minidump format encodes enough information about each module's memory 363 // range to allow us to create placeholder modules. 364 // 365 // This enables most LLDB functionality involving address-to-module 366 // translations (ex. identifing the module for a stack frame PC) and 367 // modules/sections commands (ex. target modules list, ...) 368 if (log) { 369 log->Printf("Unable to locate the matching object file, creating a " 370 "placeholder module for: %s", 371 name.getValue().c_str()); 372 } 373 374 auto placeholder_module = 375 std::make_shared<PlaceholderModule>(module_spec); 376 placeholder_module->CreateImageSection(module, GetTarget()); 377 module_sp = placeholder_module; 378 GetTarget().GetImages().Append(module_sp); 379 } 380 381 if (log) { 382 log->Printf("ProcessMinidump::%s load module: name: %s", __FUNCTION__, 383 name.getValue().c_str()); 384 } 385 386 bool load_addr_changed = false; 387 module_sp->SetLoadAddress(GetTarget(), module->base_of_image, false, 388 load_addr_changed); 389 } 390 } 391 392 bool ProcessMinidump::GetProcessInfo(ProcessInstanceInfo &info) { 393 info.Clear(); 394 info.SetProcessID(GetID()); 395 info.SetArchitecture(GetArchitecture()); 396 lldb::ModuleSP module_sp = GetTarget().GetExecutableModule(); 397 if (module_sp) { 398 const bool add_exe_file_as_first_arg = false; 399 info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(), 400 add_exe_file_as_first_arg); 401 } 402 return true; 403 } 404