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/Core/State.h" 20 #include "lldb/Target/DynamicLoader.h" 21 #include "lldb/Target/MemoryRegionInfo.h" 22 #include "lldb/Target/SectionLoadList.h" 23 #include "lldb/Target/Target.h" 24 #include "lldb/Target/UnixSignals.h" 25 #include "lldb/Utility/DataBufferLLVM.h" 26 #include "lldb/Utility/LLDBAssert.h" 27 #include "lldb/Utility/Log.h" 28 29 #include "llvm/Support/MemoryBuffer.h" 30 #include "llvm/Support/Threading.h" 31 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 = 104 DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(), 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 = DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(), -1, 0); 117 if (!AllData) 118 return nullptr; 119 120 auto minidump_parser = MinidumpParser::Create(AllData); 121 // check if the parser object is valid 122 if (!minidump_parser) 123 return nullptr; 124 125 return std::make_shared<ProcessMinidump>(target_sp, listener_sp, *crash_file, 126 minidump_parser.getValue()); 127 } 128 129 bool ProcessMinidump::CanDebug(lldb::TargetSP target_sp, 130 bool plugin_specified_by_name) { 131 return true; 132 } 133 134 ProcessMinidump::ProcessMinidump(lldb::TargetSP target_sp, 135 lldb::ListenerSP listener_sp, 136 const FileSpec &core_file, 137 MinidumpParser minidump_parser) 138 : Process(target_sp, listener_sp), m_minidump_parser(minidump_parser), 139 m_core_file(core_file), m_is_wow64(false) {} 140 141 ProcessMinidump::~ProcessMinidump() { 142 Clear(); 143 // We need to call finalize on the process before destroying ourselves to 144 // make sure all of the broadcaster cleanup goes as planned. If we destruct 145 // this class, then Process::~Process() might have problems trying to fully 146 // destroy the broadcaster. 147 Finalize(); 148 } 149 150 void ProcessMinidump::Initialize() { 151 static llvm::once_flag g_once_flag; 152 153 llvm::call_once(g_once_flag, []() { 154 PluginManager::RegisterPlugin(GetPluginNameStatic(), 155 GetPluginDescriptionStatic(), 156 ProcessMinidump::CreateInstance); 157 }); 158 } 159 160 void ProcessMinidump::Terminate() { 161 PluginManager::UnregisterPlugin(ProcessMinidump::CreateInstance); 162 } 163 164 Status ProcessMinidump::DoLoadCore() { 165 Status error; 166 167 // Minidump parser initialization & consistency checks 168 error = m_minidump_parser.Initialize(); 169 if (error.Fail()) 170 return error; 171 172 // Do we support the minidump's architecture? 173 ArchSpec arch = GetArchitecture(); 174 switch (arch.GetMachine()) { 175 case llvm::Triple::x86: 176 case llvm::Triple::x86_64: 177 // supported 178 break; 179 180 default: 181 error.SetErrorStringWithFormat("unsupported minidump architecture: %s", 182 arch.GetArchitectureName()); 183 return error; 184 } 185 186 m_thread_list = m_minidump_parser.GetThreads(); 187 m_active_exception = m_minidump_parser.GetExceptionStream(); 188 ReadModuleList(); 189 GetTarget().SetArchitecture(arch); 190 191 llvm::Optional<lldb::pid_t> pid = m_minidump_parser.GetPid(); 192 if (!pid) { 193 error.SetErrorString("failed to parse PID"); 194 return error; 195 } 196 SetID(pid.getValue()); 197 198 return error; 199 } 200 201 DynamicLoader *ProcessMinidump::GetDynamicLoader() { 202 if (m_dyld_ap.get() == nullptr) 203 m_dyld_ap.reset(DynamicLoader::FindPlugin(this, nullptr)); 204 return m_dyld_ap.get(); 205 } 206 207 ConstString ProcessMinidump::GetPluginName() { return GetPluginNameStatic(); } 208 209 uint32_t ProcessMinidump::GetPluginVersion() { return 1; } 210 211 Status ProcessMinidump::DoDestroy() { return Status(); } 212 213 void ProcessMinidump::RefreshStateAfterStop() { 214 if (!m_active_exception) 215 return; 216 217 if (m_active_exception->exception_record.exception_code == 218 MinidumpException::DumpRequested) { 219 return; 220 } 221 222 lldb::StopInfoSP stop_info; 223 lldb::ThreadSP stop_thread; 224 225 Process::m_thread_list.SetSelectedThreadByID(m_active_exception->thread_id); 226 stop_thread = Process::m_thread_list.GetSelectedThread(); 227 ArchSpec arch = GetArchitecture(); 228 229 if (arch.GetTriple().getOS() == llvm::Triple::Linux) { 230 stop_info = StopInfo::CreateStopReasonWithSignal( 231 *stop_thread, m_active_exception->exception_record.exception_code); 232 } else { 233 std::string desc; 234 llvm::raw_string_ostream desc_stream(desc); 235 desc_stream << "Exception " 236 << llvm::format_hex( 237 m_active_exception->exception_record.exception_code, 8) 238 << " encountered at address " 239 << llvm::format_hex( 240 m_active_exception->exception_record.exception_address, 241 8); 242 stop_info = StopInfo::CreateStopReasonWithException( 243 *stop_thread, desc_stream.str().c_str()); 244 } 245 246 stop_thread->SetStopInfo(stop_info); 247 } 248 249 bool ProcessMinidump::IsAlive() { return true; } 250 251 bool ProcessMinidump::WarnBeforeDetach() const { return false; } 252 253 size_t ProcessMinidump::ReadMemory(lldb::addr_t addr, void *buf, size_t size, 254 Status &error) { 255 // Don't allow the caching that lldb_private::Process::ReadMemory does since 256 // we have it all cached in our dump file anyway. 257 return DoReadMemory(addr, buf, size, error); 258 } 259 260 size_t ProcessMinidump::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, 261 Status &error) { 262 263 llvm::ArrayRef<uint8_t> mem = m_minidump_parser.GetMemory(addr, size); 264 if (mem.empty()) { 265 error.SetErrorString("could not parse memory info"); 266 return 0; 267 } 268 269 std::memcpy(buf, mem.data(), mem.size()); 270 return mem.size(); 271 } 272 273 ArchSpec ProcessMinidump::GetArchitecture() { 274 if (!m_is_wow64) { 275 return m_minidump_parser.GetArchitecture(); 276 } 277 278 llvm::Triple triple; 279 triple.setVendor(llvm::Triple::VendorType::UnknownVendor); 280 triple.setArch(llvm::Triple::ArchType::x86); 281 triple.setOS(llvm::Triple::OSType::Win32); 282 return ArchSpec(triple); 283 } 284 285 Status ProcessMinidump::GetMemoryRegionInfo(lldb::addr_t load_addr, 286 MemoryRegionInfo &range_info) { 287 Status error; 288 auto info = m_minidump_parser.GetMemoryRegionInfo(load_addr); 289 if (!info) { 290 error.SetErrorString("No valid MemoryRegionInfo found!"); 291 return error; 292 } 293 range_info = info.getValue(); 294 return error; 295 } 296 297 void ProcessMinidump::Clear() { Process::m_thread_list.Clear(); } 298 299 bool ProcessMinidump::UpdateThreadList(ThreadList &old_thread_list, 300 ThreadList &new_thread_list) { 301 uint32_t num_threads = 0; 302 if (m_thread_list.size() > 0) 303 num_threads = m_thread_list.size(); 304 305 for (lldb::tid_t tid = 0; tid < num_threads; ++tid) { 306 llvm::ArrayRef<uint8_t> context; 307 if (!m_is_wow64) 308 context = m_minidump_parser.GetThreadContext(m_thread_list[tid]); 309 else 310 context = m_minidump_parser.GetThreadContextWow64(m_thread_list[tid]); 311 312 lldb::ThreadSP thread_sp( 313 new ThreadMinidump(*this, m_thread_list[tid], context)); 314 new_thread_list.AddThread(thread_sp); 315 } 316 return new_thread_list.GetSize(false) > 0; 317 } 318 319 void ProcessMinidump::ReadModuleList() { 320 std::vector<const MinidumpModule *> filtered_modules = 321 m_minidump_parser.GetFilteredModuleList(); 322 323 for (auto module : filtered_modules) { 324 llvm::Optional<std::string> name = 325 m_minidump_parser.GetMinidumpString(module->module_name_rva); 326 327 if (!name) 328 continue; 329 330 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES)); 331 if (log) { 332 log->Printf("ProcessMinidump::%s found module: name: %s %#010" PRIx64 333 "-%#010" PRIx64 " size: %" PRIu32, 334 __FUNCTION__, name.getValue().c_str(), 335 uint64_t(module->base_of_image), 336 module->base_of_image + module->size_of_image, 337 uint32_t(module->size_of_image)); 338 } 339 340 // check if the process is wow64 - a 32 bit windows process running on a 341 // 64 bit windows 342 if (llvm::StringRef(name.getValue()).endswith_lower("wow64.dll")) { 343 m_is_wow64 = true; 344 } 345 346 const auto uuid = m_minidump_parser.GetModuleUUID(module); 347 const auto file_spec = 348 FileSpec(name.getValue(), true, GetArchitecture().GetTriple()); 349 ModuleSpec module_spec(file_spec, uuid); 350 Status error; 351 lldb::ModuleSP module_sp = GetTarget().GetSharedModule(module_spec, &error); 352 if (!module_sp || error.Fail()) { 353 // We failed to locate a matching local object file. Fortunately, the 354 // minidump format encodes enough information about each module's memory 355 // range to allow us to create placeholder modules. 356 // 357 // This enables most LLDB functionality involving address-to-module 358 // translations (ex. identifing the module for a stack frame PC) and 359 // modules/sections commands (ex. target modules list, ...) 360 auto placeholder_module = 361 std::make_shared<PlaceholderModule>(module_spec); 362 placeholder_module->CreateImageSection(module, GetTarget()); 363 module_sp = placeholder_module; 364 GetTarget().GetImages().Append(module_sp); 365 } 366 367 if (log) { 368 log->Printf("ProcessMinidump::%s load module: name: %s", __FUNCTION__, 369 name.getValue().c_str()); 370 } 371 372 bool load_addr_changed = false; 373 module_sp->SetLoadAddress(GetTarget(), module->base_of_image, false, 374 load_addr_changed); 375 } 376 } 377 378 bool ProcessMinidump::GetProcessInfo(ProcessInstanceInfo &info) { 379 info.Clear(); 380 info.SetProcessID(GetID()); 381 info.SetArchitecture(GetArchitecture()); 382 lldb::ModuleSP module_sp = GetTarget().GetExecutableModule(); 383 if (module_sp) { 384 const bool add_exe_file_as_first_arg = false; 385 info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(), 386 add_exe_file_as_first_arg); 387 } 388 return true; 389 } 390