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 assert(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 m_thread_list = m_minidump_parser.GetThreads(); 168 m_active_exception = m_minidump_parser.GetExceptionStream(); 169 ReadModuleList(); 170 GetTarget().SetArchitecture(GetArchitecture()); 171 172 llvm::Optional<lldb::pid_t> pid = m_minidump_parser.GetPid(); 173 if (!pid) { 174 error.SetErrorString("failed to parse PID"); 175 return error; 176 } 177 SetID(pid.getValue()); 178 179 return error; 180 } 181 182 DynamicLoader *ProcessMinidump::GetDynamicLoader() { 183 if (m_dyld_ap.get() == nullptr) 184 m_dyld_ap.reset(DynamicLoader::FindPlugin(this, nullptr)); 185 return m_dyld_ap.get(); 186 } 187 188 ConstString ProcessMinidump::GetPluginName() { return GetPluginNameStatic(); } 189 190 uint32_t ProcessMinidump::GetPluginVersion() { return 1; } 191 192 Status ProcessMinidump::DoDestroy() { return Status(); } 193 194 void ProcessMinidump::RefreshStateAfterStop() { 195 if (!m_active_exception) 196 return; 197 198 if (m_active_exception->exception_record.exception_code == 199 MinidumpException::DumpRequested) { 200 return; 201 } 202 203 lldb::StopInfoSP stop_info; 204 lldb::ThreadSP stop_thread; 205 206 Process::m_thread_list.SetSelectedThreadByID(m_active_exception->thread_id); 207 stop_thread = Process::m_thread_list.GetSelectedThread(); 208 ArchSpec arch = GetArchitecture(); 209 210 if (arch.GetTriple().getOS() == llvm::Triple::Linux) { 211 stop_info = StopInfo::CreateStopReasonWithSignal( 212 *stop_thread, m_active_exception->exception_record.exception_code); 213 } else { 214 std::string desc; 215 llvm::raw_string_ostream desc_stream(desc); 216 desc_stream << "Exception " 217 << llvm::format_hex( 218 m_active_exception->exception_record.exception_code, 8) 219 << " encountered at address " 220 << llvm::format_hex( 221 m_active_exception->exception_record.exception_address, 222 8); 223 stop_info = StopInfo::CreateStopReasonWithException( 224 *stop_thread, desc_stream.str().c_str()); 225 } 226 227 stop_thread->SetStopInfo(stop_info); 228 } 229 230 bool ProcessMinidump::IsAlive() { return true; } 231 232 bool ProcessMinidump::WarnBeforeDetach() const { return false; } 233 234 size_t ProcessMinidump::ReadMemory(lldb::addr_t addr, void *buf, size_t size, 235 Status &error) { 236 // Don't allow the caching that lldb_private::Process::ReadMemory does since 237 // we have it all cached in our dump file anyway. 238 return DoReadMemory(addr, buf, size, error); 239 } 240 241 size_t ProcessMinidump::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, 242 Status &error) { 243 244 llvm::ArrayRef<uint8_t> mem = m_minidump_parser.GetMemory(addr, size); 245 if (mem.empty()) { 246 error.SetErrorString("could not parse memory info"); 247 return 0; 248 } 249 250 std::memcpy(buf, mem.data(), mem.size()); 251 return mem.size(); 252 } 253 254 ArchSpec ProcessMinidump::GetArchitecture() { 255 if (!m_is_wow64) { 256 return m_minidump_parser.GetArchitecture(); 257 } 258 259 llvm::Triple triple; 260 triple.setVendor(llvm::Triple::VendorType::UnknownVendor); 261 triple.setArch(llvm::Triple::ArchType::x86); 262 triple.setOS(llvm::Triple::OSType::Win32); 263 return ArchSpec(triple); 264 } 265 266 Status ProcessMinidump::GetMemoryRegionInfo(lldb::addr_t load_addr, 267 MemoryRegionInfo &range_info) { 268 Status error; 269 auto info = m_minidump_parser.GetMemoryRegionInfo(load_addr); 270 if (!info) { 271 error.SetErrorString("No valid MemoryRegionInfo found!"); 272 return error; 273 } 274 range_info = info.getValue(); 275 return error; 276 } 277 278 void ProcessMinidump::Clear() { Process::m_thread_list.Clear(); } 279 280 bool ProcessMinidump::UpdateThreadList(ThreadList &old_thread_list, 281 ThreadList &new_thread_list) { 282 uint32_t num_threads = 0; 283 if (m_thread_list.size() > 0) 284 num_threads = m_thread_list.size(); 285 286 for (lldb::tid_t tid = 0; tid < num_threads; ++tid) { 287 llvm::ArrayRef<uint8_t> context; 288 if (!m_is_wow64) 289 context = m_minidump_parser.GetThreadContext(m_thread_list[tid]); 290 else 291 context = m_minidump_parser.GetThreadContextWow64(m_thread_list[tid]); 292 293 lldb::ThreadSP thread_sp( 294 new ThreadMinidump(*this, m_thread_list[tid], context)); 295 new_thread_list.AddThread(thread_sp); 296 } 297 return new_thread_list.GetSize(false) > 0; 298 } 299 300 void ProcessMinidump::ReadModuleList() { 301 std::vector<const MinidumpModule *> filtered_modules = 302 m_minidump_parser.GetFilteredModuleList(); 303 304 for (auto module : filtered_modules) { 305 llvm::Optional<std::string> name = 306 m_minidump_parser.GetMinidumpString(module->module_name_rva); 307 308 if (!name) 309 continue; 310 311 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES)); 312 if (log) { 313 log->Printf("ProcessMinidump::%s found module: name: %s %#010" PRIx64 314 "-%#010" PRIx64 " size: %" PRIu32, 315 __FUNCTION__, name.getValue().c_str(), 316 uint64_t(module->base_of_image), 317 module->base_of_image + module->size_of_image, 318 uint32_t(module->size_of_image)); 319 } 320 321 // check if the process is wow64 - a 32 bit windows process running on a 322 // 64 bit windows 323 if (llvm::StringRef(name.getValue()).endswith_lower("wow64.dll")) { 324 m_is_wow64 = true; 325 } 326 327 const auto uuid = m_minidump_parser.GetModuleUUID(module); 328 const auto file_spec = 329 FileSpec(name.getValue(), true, GetArchitecture().GetTriple()); 330 ModuleSpec module_spec(file_spec, uuid); 331 Status error; 332 lldb::ModuleSP module_sp = GetTarget().GetSharedModule(module_spec, &error); 333 if (!module_sp || error.Fail()) { 334 // We failed to locate a matching local object file. Fortunately, the 335 // minidump format encodes enough information about each module's memory 336 // range to allow us to create placeholder modules. 337 // 338 // This enables most LLDB functionality involving address-to-module 339 // translations (ex. identifing the module for a stack frame PC) and 340 // modules/sections commands (ex. target modules list, ...) 341 auto placeholder_module = 342 std::make_shared<PlaceholderModule>(module_spec); 343 placeholder_module->CreateImageSection(module, GetTarget()); 344 module_sp = placeholder_module; 345 GetTarget().GetImages().Append(module_sp); 346 } 347 348 if (log) { 349 log->Printf("ProcessMinidump::%s load module: name: %s", __FUNCTION__, 350 name.getValue().c_str()); 351 } 352 353 bool load_addr_changed = false; 354 module_sp->SetLoadAddress(GetTarget(), module->base_of_image, false, 355 load_addr_changed); 356 } 357 } 358 359 bool ProcessMinidump::GetProcessInfo(ProcessInstanceInfo &info) { 360 info.Clear(); 361 info.SetProcessID(GetID()); 362 info.SetArchitecture(GetArchitecture()); 363 lldb::ModuleSP module_sp = GetTarget().GetExecutableModule(); 364 if (module_sp) { 365 const bool add_exe_file_as_first_arg = false; 366 info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(), 367 add_exe_file_as_first_arg); 368 } 369 return true; 370 } 371