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/JITLoaderList.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/LLDBAssert.h" 25 #include "lldb/Utility/Log.h" 26 #include "lldb/Utility/State.h" 27 28 #include "llvm/Support/MemoryBuffer.h" 29 #include "llvm/Support/Threading.h" 30 31 #include "Plugins/Process/Utility/StopInfoMachException.h" 32 // C includes 33 // C++ includes 34 35 using namespace lldb; 36 using namespace lldb_private; 37 using namespace minidump; 38 39 //------------------------------------------------------------------ 40 /// A placeholder module used for minidumps, where the original 41 /// object files may not be available (so we can't parse the object 42 /// files to extract the set of sections/segments) 43 /// 44 /// This placeholder module has a single synthetic section (.module_image) 45 /// which represents the module memory range covering the whole module. 46 //------------------------------------------------------------------ 47 class PlaceholderModule : public Module { 48 public: 49 PlaceholderModule(const ModuleSpec &module_spec) : 50 Module(module_spec.GetFileSpec(), module_spec.GetArchitecture()) { 51 if (module_spec.GetUUID().IsValid()) 52 SetUUID(module_spec.GetUUID()); 53 } 54 55 // Creates a synthetic module section covering the whole module image (and 56 // sets the section load address as well) 57 void CreateImageSection(const MinidumpModule *module, Target& target) { 58 const ConstString section_name(".module_image"); 59 lldb::SectionSP section_sp(new Section( 60 shared_from_this(), // Module to which this section belongs. 61 nullptr, // ObjectFile 62 0, // Section ID. 63 section_name, // Section name. 64 eSectionTypeContainer, // Section type. 65 module->base_of_image, // VM address. 66 module->size_of_image, // VM size in bytes of this section. 67 0, // Offset of this section in the file. 68 module->size_of_image, // Size of the section as found in the file. 69 12, // Alignment of the section (log2) 70 0, // Flags for this section. 71 1)); // Number of host bytes per target byte 72 section_sp->SetPermissions(ePermissionsExecutable | ePermissionsReadable); 73 GetSectionList()->AddSection(section_sp); 74 target.GetSectionLoadList().SetSectionLoadAddress( 75 section_sp, module->base_of_image); 76 } 77 78 ObjectFile *GetObjectFile() override { return nullptr; } 79 80 SectionList *GetSectionList() override { 81 return Module::GetUnifiedSectionList(); 82 } 83 }; 84 85 ConstString ProcessMinidump::GetPluginNameStatic() { 86 static ConstString g_name("minidump"); 87 return g_name; 88 } 89 90 const char *ProcessMinidump::GetPluginDescriptionStatic() { 91 return "Minidump plug-in."; 92 } 93 94 lldb::ProcessSP ProcessMinidump::CreateInstance(lldb::TargetSP target_sp, 95 lldb::ListenerSP listener_sp, 96 const FileSpec *crash_file) { 97 if (!crash_file) 98 return nullptr; 99 100 lldb::ProcessSP process_sp; 101 // Read enough data for the Minidump header 102 constexpr size_t header_size = sizeof(MinidumpHeader); 103 auto DataPtr = FileSystem::Instance().CreateDataBuffer(crash_file->GetPath(), 104 header_size, 0); 105 if (!DataPtr) 106 return nullptr; 107 108 lldbassert(DataPtr->GetByteSize() == header_size); 109 110 // first, only try to parse the header, beacuse we need to be fast 111 llvm::ArrayRef<uint8_t> HeaderBytes = DataPtr->GetData(); 112 const MinidumpHeader *header = MinidumpHeader::Parse(HeaderBytes); 113 if (header == nullptr) 114 return nullptr; 115 116 auto AllData = 117 FileSystem::Instance().CreateDataBuffer(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 ConstString ProcessMinidump::GetPluginName() { return GetPluginNameStatic(); } 205 206 uint32_t ProcessMinidump::GetPluginVersion() { return 1; } 207 208 Status ProcessMinidump::DoDestroy() { return Status(); } 209 210 void ProcessMinidump::RefreshStateAfterStop() { 211 if (!m_active_exception) 212 return; 213 214 if (m_active_exception->exception_record.exception_code == 215 MinidumpException::DumpRequested) { 216 return; 217 } 218 219 lldb::StopInfoSP stop_info; 220 lldb::ThreadSP stop_thread; 221 222 Process::m_thread_list.SetSelectedThreadByID(m_active_exception->thread_id); 223 stop_thread = Process::m_thread_list.GetSelectedThread(); 224 ArchSpec arch = GetArchitecture(); 225 226 if (arch.GetTriple().getOS() == llvm::Triple::Linux) { 227 stop_info = StopInfo::CreateStopReasonWithSignal( 228 *stop_thread, m_active_exception->exception_record.exception_code); 229 } else if (arch.GetTriple().getVendor() == llvm::Triple::Apple) { 230 stop_info = StopInfoMachException::CreateStopReasonWithMachException( 231 *stop_thread, m_active_exception->exception_record.exception_code, 2, 232 m_active_exception->exception_record.exception_flags, 233 m_active_exception->exception_record.exception_address, 0); 234 } else { 235 std::string desc; 236 llvm::raw_string_ostream desc_stream(desc); 237 desc_stream << "Exception " 238 << llvm::format_hex( 239 m_active_exception->exception_record.exception_code, 8) 240 << " encountered at address " 241 << llvm::format_hex( 242 m_active_exception->exception_record.exception_address, 243 8); 244 stop_info = StopInfo::CreateStopReasonWithException( 245 *stop_thread, desc_stream.str().c_str()); 246 } 247 248 stop_thread->SetStopInfo(stop_info); 249 } 250 251 bool ProcessMinidump::IsAlive() { return true; } 252 253 bool ProcessMinidump::WarnBeforeDetach() const { return false; } 254 255 size_t ProcessMinidump::ReadMemory(lldb::addr_t addr, void *buf, size_t size, 256 Status &error) { 257 // Don't allow the caching that lldb_private::Process::ReadMemory does since 258 // we have it all cached in our dump file anyway. 259 return DoReadMemory(addr, buf, size, error); 260 } 261 262 size_t ProcessMinidump::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, 263 Status &error) { 264 265 llvm::ArrayRef<uint8_t> mem = m_minidump_parser.GetMemory(addr, size); 266 if (mem.empty()) { 267 error.SetErrorString("could not parse memory info"); 268 return 0; 269 } 270 271 std::memcpy(buf, mem.data(), mem.size()); 272 return mem.size(); 273 } 274 275 ArchSpec ProcessMinidump::GetArchitecture() { 276 if (!m_is_wow64) { 277 return m_minidump_parser.GetArchitecture(); 278 } 279 280 llvm::Triple triple; 281 triple.setVendor(llvm::Triple::VendorType::UnknownVendor); 282 triple.setArch(llvm::Triple::ArchType::x86); 283 triple.setOS(llvm::Triple::OSType::Win32); 284 return ArchSpec(triple); 285 } 286 287 Status ProcessMinidump::GetMemoryRegionInfo(lldb::addr_t load_addr, 288 MemoryRegionInfo &range_info) { 289 Status error; 290 auto info = m_minidump_parser.GetMemoryRegionInfo(load_addr); 291 if (!info) { 292 error.SetErrorString("No valid MemoryRegionInfo found!"); 293 return error; 294 } 295 range_info = info.getValue(); 296 return error; 297 } 298 299 void ProcessMinidump::Clear() { Process::m_thread_list.Clear(); } 300 301 bool ProcessMinidump::UpdateThreadList(ThreadList &old_thread_list, 302 ThreadList &new_thread_list) { 303 uint32_t num_threads = 0; 304 if (m_thread_list.size() > 0) 305 num_threads = m_thread_list.size(); 306 307 for (lldb::tid_t tid = 0; tid < num_threads; ++tid) { 308 llvm::ArrayRef<uint8_t> context; 309 if (!m_is_wow64) 310 context = m_minidump_parser.GetThreadContext(m_thread_list[tid]); 311 else 312 context = m_minidump_parser.GetThreadContextWow64(m_thread_list[tid]); 313 314 lldb::ThreadSP thread_sp( 315 new ThreadMinidump(*this, m_thread_list[tid], context)); 316 new_thread_list.AddThread(thread_sp); 317 } 318 return new_thread_list.GetSize(false) > 0; 319 } 320 321 void ProcessMinidump::ReadModuleList() { 322 std::vector<const MinidumpModule *> filtered_modules = 323 m_minidump_parser.GetFilteredModuleList(); 324 325 for (auto module : filtered_modules) { 326 llvm::Optional<std::string> name = 327 m_minidump_parser.GetMinidumpString(module->module_name_rva); 328 329 if (!name) 330 continue; 331 332 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES)); 333 if (log) { 334 log->Printf("ProcessMinidump::%s found module: name: %s %#010" PRIx64 335 "-%#010" PRIx64 " size: %" PRIu32, 336 __FUNCTION__, name.getValue().c_str(), 337 uint64_t(module->base_of_image), 338 module->base_of_image + module->size_of_image, 339 uint32_t(module->size_of_image)); 340 } 341 342 // check if the process is wow64 - a 32 bit windows process running on a 343 // 64 bit windows 344 if (llvm::StringRef(name.getValue()).endswith_lower("wow64.dll")) { 345 m_is_wow64 = true; 346 } 347 348 const auto uuid = m_minidump_parser.GetModuleUUID(module); 349 auto file_spec = FileSpec(name.getValue(), GetArchitecture().GetTriple()); 350 FileSystem::Instance().Resolve(file_spec); 351 ModuleSpec module_spec(file_spec, uuid); 352 Status error; 353 lldb::ModuleSP module_sp = GetTarget().GetSharedModule(module_spec, &error); 354 if (!module_sp || error.Fail()) { 355 // We failed to locate a matching local object file. Fortunately, the 356 // minidump format encodes enough information about each module's memory 357 // range to allow us to create placeholder modules. 358 // 359 // This enables most LLDB functionality involving address-to-module 360 // translations (ex. identifing the module for a stack frame PC) and 361 // modules/sections commands (ex. target modules list, ...) 362 if (log) { 363 log->Printf("Unable to locate the matching object file, creating a " 364 "placeholder module for: %s", 365 name.getValue().c_str()); 366 } 367 368 auto placeholder_module = 369 std::make_shared<PlaceholderModule>(module_spec); 370 placeholder_module->CreateImageSection(module, GetTarget()); 371 module_sp = placeholder_module; 372 GetTarget().GetImages().Append(module_sp); 373 } 374 375 if (log) { 376 log->Printf("ProcessMinidump::%s load module: name: %s", __FUNCTION__, 377 name.getValue().c_str()); 378 } 379 380 bool load_addr_changed = false; 381 module_sp->SetLoadAddress(GetTarget(), module->base_of_image, false, 382 load_addr_changed); 383 } 384 } 385 386 bool ProcessMinidump::GetProcessInfo(ProcessInstanceInfo &info) { 387 info.Clear(); 388 info.SetProcessID(GetID()); 389 info.SetArchitecture(GetArchitecture()); 390 lldb::ModuleSP module_sp = GetTarget().GetExecutableModule(); 391 if (module_sp) { 392 const bool add_exe_file_as_first_arg = false; 393 info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(), 394 add_exe_file_as_first_arg); 395 } 396 return true; 397 } 398 399 // For minidumps there's no runtime generated code so we don't need JITLoader(s) 400 // Avoiding them will also speed up minidump loading since JITLoaders normally 401 // try to set up symbolic breakpoints, which in turn may force loading more 402 // debug information than needed. 403 JITLoaderList &ProcessMinidump::GetJITLoaders() { 404 if (!m_jit_loaders_ap) { 405 m_jit_loaders_ap = llvm::make_unique<JITLoaderList>(); 406 } 407 return *m_jit_loaders_ap; 408 } 409