diff options
Diffstat (limited to 'source/Plugins/Process/minidump/ProcessMinidump.cpp')
-rw-r--r-- | source/Plugins/Process/minidump/ProcessMinidump.cpp | 469 |
1 files changed, 320 insertions, 149 deletions
diff --git a/source/Plugins/Process/minidump/ProcessMinidump.cpp b/source/Plugins/Process/minidump/ProcessMinidump.cpp index c5cca7ea62c6..a7fc42cad16c 100644 --- a/source/Plugins/Process/minidump/ProcessMinidump.cpp +++ b/source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -1,13 +1,13 @@ //===-- ProcessMinidump.cpp -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "ProcessMinidump.h" + #include "ThreadMinidump.h" #include "lldb/Core/DumpDataExtractor.h" @@ -29,64 +29,93 @@ #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/State.h" - +#include "llvm/BinaryFormat/Magic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Threading.h" #include "Plugins/Process/Utility/StopInfoMachException.h" -// C includes -// C++ includes +#include <memory> using namespace lldb; using namespace lldb_private; using namespace minidump; -//------------------------------------------------------------------ -/// A placeholder module used for minidumps, where the original -/// object files may not be available (so we can't parse the object -/// files to extract the set of sections/segments) -/// -/// This placeholder module has a single synthetic section (.module_image) -/// which represents the module memory range covering the whole module. -//------------------------------------------------------------------ -class PlaceholderModule : public Module { +namespace { + +/// A minimal ObjectFile implementation providing a dummy object file for the +/// cases when the real module binary is not available. This allows the module +/// to show up in "image list" and symbols to be added to it. +class PlaceholderObjectFile : public ObjectFile { public: - PlaceholderModule(const ModuleSpec &module_spec) : - Module(module_spec.GetFileSpec(), module_spec.GetArchitecture()) { - if (module_spec.GetUUID().IsValid()) - SetUUID(module_spec.GetUUID()); - } - - // Creates a synthetic module section covering the whole module image (and - // sets the section load address as well) - void CreateImageSection(const MinidumpModule *module, Target& target) { - const ConstString section_name(".module_image"); - lldb::SectionSP section_sp(new Section( - shared_from_this(), // Module to which this section belongs. - nullptr, // ObjectFile - 0, // Section ID. - section_name, // Section name. - eSectionTypeContainer, // Section type. - module->base_of_image, // VM address. - module->size_of_image, // VM size in bytes of this section. - 0, // Offset of this section in the file. - module->size_of_image, // Size of the section as found in the file. - 12, // Alignment of the section (log2) - 0, // Flags for this section. - 1)); // Number of host bytes per target byte - section_sp->SetPermissions(ePermissionsExecutable | ePermissionsReadable); - GetSectionList()->AddSection(section_sp); - target.GetSectionLoadList().SetSectionLoadAddress( - section_sp, module->base_of_image); + PlaceholderObjectFile(const lldb::ModuleSP &module_sp, + const ModuleSpec &module_spec, lldb::offset_t base, + lldb::offset_t size) + : ObjectFile(module_sp, &module_spec.GetFileSpec(), /*file_offset*/ 0, + /*length*/ 0, /*data_sp*/ nullptr, /*data_offset*/ 0), + m_arch(module_spec.GetArchitecture()), m_uuid(module_spec.GetUUID()), + m_base(base), m_size(size) { + m_symtab_up = llvm::make_unique<Symtab>(this); } -ObjectFile *GetObjectFile() override { return nullptr; } + ConstString GetPluginName() override { return ConstString("placeholder"); } + uint32_t GetPluginVersion() override { return 1; } + bool ParseHeader() override { return true; } + Type CalculateType() override { return eTypeUnknown; } + Strata CalculateStrata() override { return eStrataUnknown; } + uint32_t GetDependentModules(FileSpecList &file_list) override { return 0; } + bool IsExecutable() const override { return false; } + ArchSpec GetArchitecture() override { return m_arch; } + UUID GetUUID() override { return m_uuid; } + Symtab *GetSymtab() override { return m_symtab_up.get(); } + bool IsStripped() override { return true; } + ByteOrder GetByteOrder() const override { return m_arch.GetByteOrder(); } + + uint32_t GetAddressByteSize() const override { + return m_arch.GetAddressByteSize(); + } - SectionList *GetSectionList() override { - return Module::GetUnifiedSectionList(); + Address GetBaseAddress() override { + return Address(m_sections_up->GetSectionAtIndex(0), 0); } + + void CreateSections(SectionList &unified_section_list) override { + m_sections_up = llvm::make_unique<SectionList>(); + auto section_sp = std::make_shared<Section>( + GetModule(), this, /*sect_id*/ 0, ConstString(".module_image"), + eSectionTypeOther, m_base, m_size, /*file_offset*/ 0, /*file_size*/ 0, + /*log2align*/ 0, /*flags*/ 0); + section_sp->SetPermissions(ePermissionsReadable | ePermissionsExecutable); + m_sections_up->AddSection(section_sp); + unified_section_list.AddSection(std::move(section_sp)); + } + + bool SetLoadAddress(Target &target, addr_t value, + bool value_is_offset) override { + assert(!value_is_offset); + assert(value == m_base); + + // Create sections if they haven't been created already. + GetModule()->GetSectionList(); + assert(m_sections_up->GetNumSections(0) == 1); + + target.GetSectionLoadList().SetSectionLoadAddress( + m_sections_up->GetSectionAtIndex(0), m_base); + return true; + } + + void Dump(Stream *s) override { + s->Format("Placeholder object file for {0} loaded at [{1:x}-{2:x})\n", + GetFileSpec(), m_base, m_base + m_size); + } + +private: + ArchSpec m_arch; + UUID m_uuid; + lldb::offset_t m_base; + lldb::offset_t m_size; }; +} // namespace ConstString ProcessMinidump::GetPluginNameStatic() { static ConstString g_name("minidump"); @@ -105,18 +134,14 @@ lldb::ProcessSP ProcessMinidump::CreateInstance(lldb::TargetSP target_sp, lldb::ProcessSP process_sp; // Read enough data for the Minidump header - constexpr size_t header_size = sizeof(MinidumpHeader); + constexpr size_t header_size = sizeof(Header); auto DataPtr = FileSystem::Instance().CreateDataBuffer(crash_file->GetPath(), header_size, 0); if (!DataPtr) return nullptr; lldbassert(DataPtr->GetByteSize() == header_size); - - // first, only try to parse the header, beacuse we need to be fast - llvm::ArrayRef<uint8_t> HeaderBytes = DataPtr->GetData(); - const MinidumpHeader *header = MinidumpHeader::Parse(HeaderBytes); - if (header == nullptr) + if (identify_magic(toStringRef(DataPtr->GetData())) != llvm::file_magic::minidump) return nullptr; auto AllData = @@ -124,13 +149,8 @@ lldb::ProcessSP ProcessMinidump::CreateInstance(lldb::TargetSP target_sp, if (!AllData) return nullptr; - auto minidump_parser = MinidumpParser::Create(AllData); - // check if the parser object is valid - if (!minidump_parser) - return nullptr; - return std::make_shared<ProcessMinidump>(target_sp, listener_sp, *crash_file, - minidump_parser.getValue()); + std::move(AllData)); } bool ProcessMinidump::CanDebug(lldb::TargetSP target_sp, @@ -141,9 +161,9 @@ bool ProcessMinidump::CanDebug(lldb::TargetSP target_sp, ProcessMinidump::ProcessMinidump(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec &core_file, - MinidumpParser minidump_parser) - : Process(target_sp, listener_sp), m_minidump_parser(minidump_parser), - m_core_file(core_file), m_is_wow64(false) {} + DataBufferSP core_data) + : Process(target_sp, listener_sp), m_core_file(core_file), + m_core_data(std::move(core_data)), m_is_wow64(false) {} ProcessMinidump::~ProcessMinidump() { Clear(); @@ -169,12 +189,12 @@ void ProcessMinidump::Terminate() { } Status ProcessMinidump::DoLoadCore() { - Status error; + auto expected_parser = MinidumpParser::Create(m_core_data); + if (!expected_parser) + return Status(expected_parser.takeError()); + m_minidump_parser = std::move(*expected_parser); - // Minidump parser initialization & consistency checks - error = m_minidump_parser.Initialize(); - if (error.Fail()) - return error; + Status error; // Do we support the minidump's architecture? ArchSpec arch = GetArchitecture(); @@ -193,11 +213,11 @@ Status ProcessMinidump::DoLoadCore() { } GetTarget().SetArchitecture(arch, true /*set_platform*/); - m_thread_list = m_minidump_parser.GetThreads(); - m_active_exception = m_minidump_parser.GetExceptionStream(); + m_thread_list = m_minidump_parser->GetThreads(); + m_active_exception = m_minidump_parser->GetExceptionStream(); ReadModuleList(); - llvm::Optional<lldb::pid_t> pid = m_minidump_parser.GetPid(); + llvm::Optional<lldb::pid_t> pid = m_minidump_parser->GetPid(); if (!pid) { error.SetErrorString("failed to parse PID"); return error; @@ -268,7 +288,7 @@ size_t ProcessMinidump::ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t ProcessMinidump::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Status &error) { - llvm::ArrayRef<uint8_t> mem = m_minidump_parser.GetMemory(addr, size); + llvm::ArrayRef<uint8_t> mem = m_minidump_parser->GetMemory(addr, size); if (mem.empty()) { error.SetErrorString("could not parse memory info"); return 0; @@ -280,7 +300,7 @@ size_t ProcessMinidump::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, ArchSpec ProcessMinidump::GetArchitecture() { if (!m_is_wow64) { - return m_minidump_parser.GetArchitecture(); + return m_minidump_parser->GetArchitecture(); } llvm::Triple triple; @@ -292,13 +312,13 @@ ArchSpec ProcessMinidump::GetArchitecture() { Status ProcessMinidump::GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info) { - range_info = m_minidump_parser.GetMemoryRegionInfo(load_addr); + range_info = m_minidump_parser->GetMemoryRegionInfo(load_addr); return Status(); } Status ProcessMinidump::GetMemoryRegions( lldb_private::MemoryRegionInfos ®ion_list) { - region_list = m_minidump_parser.GetMemoryRegions(); + region_list = m_minidump_parser->GetMemoryRegions(); return Status(); } @@ -306,20 +326,20 @@ void ProcessMinidump::Clear() { Process::m_thread_list.Clear(); } bool ProcessMinidump::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) { - for (const MinidumpThread& thread : m_thread_list) { - MinidumpLocationDescriptor context_location = thread.thread_context; + for (const minidump::Thread &thread : m_thread_list) { + LocationDescriptor context_location = thread.Context; // If the minidump contains an exception context, use it if (m_active_exception != nullptr && - m_active_exception->thread_id == thread.thread_id) { + m_active_exception->thread_id == thread.ThreadId) { context_location = m_active_exception->thread_context; } llvm::ArrayRef<uint8_t> context; if (!m_is_wow64) - context = m_minidump_parser.GetThreadContext(context_location); + context = m_minidump_parser->GetThreadContext(context_location); else - context = m_minidump_parser.GetThreadContextWow64(thread); + context = m_minidump_parser->GetThreadContextWow64(thread); lldb::ThreadSP thread_sp(new ThreadMinidump(*this, thread, context)); new_thread_list.AddThread(thread_sp); @@ -328,39 +348,60 @@ bool ProcessMinidump::UpdateThreadList(ThreadList &old_thread_list, } void ProcessMinidump::ReadModuleList() { - std::vector<const MinidumpModule *> filtered_modules = - m_minidump_parser.GetFilteredModuleList(); + std::vector<const minidump::Module *> filtered_modules = + m_minidump_parser->GetFilteredModuleList(); + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES)); for (auto module : filtered_modules) { - llvm::Optional<std::string> name = - m_minidump_parser.GetMinidumpString(module->module_name_rva); - - if (!name) - continue; - - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES)); - if (log) { - log->Printf("ProcessMinidump::%s found module: name: %s %#010" PRIx64 - "-%#010" PRIx64 " size: %" PRIu32, - __FUNCTION__, name.getValue().c_str(), - uint64_t(module->base_of_image), - module->base_of_image + module->size_of_image, - uint32_t(module->size_of_image)); - } + std::string name = cantFail(m_minidump_parser->GetMinidumpFile().getString( + module->ModuleNameRVA)); + LLDB_LOG(log, "found module: name: {0} {1:x10}-{2:x10} size: {3}", name, + module->BaseOfImage, module->BaseOfImage + module->SizeOfImage, + module->SizeOfImage); // check if the process is wow64 - a 32 bit windows process running on a // 64 bit windows - if (llvm::StringRef(name.getValue()).endswith_lower("wow64.dll")) { + if (llvm::StringRef(name).endswith_lower("wow64.dll")) { m_is_wow64 = true; } - const auto uuid = m_minidump_parser.GetModuleUUID(module); - auto file_spec = FileSpec(name.getValue(), GetArchitecture().GetTriple()); - FileSystem::Instance().Resolve(file_spec); + const auto uuid = m_minidump_parser->GetModuleUUID(module); + auto file_spec = FileSpec(name, GetArchitecture().GetTriple()); ModuleSpec module_spec(file_spec, uuid); + module_spec.GetArchitecture() = GetArchitecture(); Status error; - lldb::ModuleSP module_sp = GetTarget().GetSharedModule(module_spec, &error); - if (!module_sp || error.Fail()) { + // Try and find a module with a full UUID that matches. This function will + // add the module to the target if it finds one. + lldb::ModuleSP module_sp = GetTarget().GetOrCreateModule(module_spec, + true /* notify */, &error); + if (!module_sp) { + // Try and find a module without specifying the UUID and only looking for + // the file given a basename. We then will look for a partial UUID match + // if we find any matches. This function will add the module to the + // target if it finds one, so we need to remove the module from the target + // if the UUID doesn't match during our manual UUID verification. This + // allows the "target.exec-search-paths" setting to specify one or more + // directories that contain executables that can be searched for matches. + ModuleSpec basename_module_spec(module_spec); + basename_module_spec.GetUUID().Clear(); + basename_module_spec.GetFileSpec().GetDirectory().Clear(); + module_sp = GetTarget().GetOrCreateModule(basename_module_spec, + true /* notify */, &error); + if (module_sp) { + // We consider the module to be a match if the minidump UUID is a + // prefix of the actual UUID, or if either of the UUIDs are empty. + const auto dmp_bytes = uuid.GetBytes(); + const auto mod_bytes = module_sp->GetUUID().GetBytes(); + const bool match = dmp_bytes.empty() || mod_bytes.empty() || + mod_bytes.take_front(dmp_bytes.size()) == dmp_bytes; + if (!match) { + GetTarget().GetImages().Remove(module_sp); + module_sp.reset(); + } + } + } + if (!module_sp) { // We failed to locate a matching local object file. Fortunately, the // minidump format encodes enough information about each module's memory // range to allow us to create placeholder modules. @@ -368,26 +409,18 @@ void ProcessMinidump::ReadModuleList() { // This enables most LLDB functionality involving address-to-module // translations (ex. identifing the module for a stack frame PC) and // modules/sections commands (ex. target modules list, ...) - if (log) { - log->Printf("Unable to locate the matching object file, creating a " - "placeholder module for: %s", - name.getValue().c_str()); - } - - auto placeholder_module = - std::make_shared<PlaceholderModule>(module_spec); - placeholder_module->CreateImageSection(module, GetTarget()); - module_sp = placeholder_module; - GetTarget().GetImages().Append(module_sp); - } - - if (log) { - log->Printf("ProcessMinidump::%s load module: name: %s", __FUNCTION__, - name.getValue().c_str()); + LLDB_LOG(log, + "Unable to locate the matching object file, creating a " + "placeholder module for: {0}", + name); + + module_sp = Module::CreateModuleFromObjectFile<PlaceholderObjectFile>( + module_spec, module->BaseOfImage, module->SizeOfImage); + GetTarget().GetImages().Append(module_sp, true /* notify */); } bool load_addr_changed = false; - module_sp->SetLoadAddress(GetTarget(), module->base_of_image, false, + module_sp->SetLoadAddress(GetTarget(), module->BaseOfImage, false, load_addr_changed); } } @@ -410,10 +443,10 @@ bool ProcessMinidump::GetProcessInfo(ProcessInstanceInfo &info) { // try to set up symbolic breakpoints, which in turn may force loading more // debug information than needed. JITLoaderList &ProcessMinidump::GetJITLoaders() { - if (!m_jit_loaders_ap) { - m_jit_loaders_ap = llvm::make_unique<JITLoaderList>(); + if (!m_jit_loaders_up) { + m_jit_loaders_up = llvm::make_unique<JITLoaderList>(); } - return *m_jit_loaders_ap; + return *m_jit_loaders_up; } #define INIT_BOOL(VAR, LONG, SHORT, DESC) \ @@ -437,10 +470,23 @@ private: OptionGroupBoolean m_dump_linux_proc_uptime; OptionGroupBoolean m_dump_linux_proc_fd; OptionGroupBoolean m_dump_linux_all; + OptionGroupBoolean m_fb_app_data; + OptionGroupBoolean m_fb_build_id; + OptionGroupBoolean m_fb_version; + OptionGroupBoolean m_fb_java_stack; + OptionGroupBoolean m_fb_dalvik; + OptionGroupBoolean m_fb_unwind; + OptionGroupBoolean m_fb_error_log; + OptionGroupBoolean m_fb_app_state; + OptionGroupBoolean m_fb_abort; + OptionGroupBoolean m_fb_thread; + OptionGroupBoolean m_fb_logcat; + OptionGroupBoolean m_fb_all; void SetDefaultOptionsIfNoneAreSet() { if (m_dump_all.GetOptionValue().GetCurrentValue() || m_dump_linux_all.GetOptionValue().GetCurrentValue() || + m_fb_all.GetOptionValue().GetCurrentValue() || m_dump_directory.GetOptionValue().GetCurrentValue() || m_dump_linux_cpuinfo.GetOptionValue().GetCurrentValue() || m_dump_linux_proc_status.GetOptionValue().GetCurrentValue() || @@ -451,7 +497,18 @@ private: m_dump_linux_maps.GetOptionValue().GetCurrentValue() || m_dump_linux_proc_stat.GetOptionValue().GetCurrentValue() || m_dump_linux_proc_uptime.GetOptionValue().GetCurrentValue() || - m_dump_linux_proc_fd.GetOptionValue().GetCurrentValue()) + m_dump_linux_proc_fd.GetOptionValue().GetCurrentValue() || + m_fb_app_data.GetOptionValue().GetCurrentValue() || + m_fb_build_id.GetOptionValue().GetCurrentValue() || + m_fb_version.GetOptionValue().GetCurrentValue() || + m_fb_java_stack.GetOptionValue().GetCurrentValue() || + m_fb_dalvik.GetOptionValue().GetCurrentValue() || + m_fb_unwind.GetOptionValue().GetCurrentValue() || + m_fb_error_log.GetOptionValue().GetCurrentValue() || + m_fb_app_state.GetOptionValue().GetCurrentValue() || + m_fb_abort.GetOptionValue().GetCurrentValue() || + m_fb_thread.GetOptionValue().GetCurrentValue() || + m_fb_logcat.GetOptionValue().GetCurrentValue()) return; // If no options were set, then dump everything m_dump_all.GetOptionValue().SetCurrentValue(true); @@ -506,11 +563,46 @@ private: return DumpLinux() || m_dump_linux_proc_fd.GetOptionValue().GetCurrentValue(); } + bool DumpFacebook() const { + return DumpAll() || m_fb_all.GetOptionValue().GetCurrentValue(); + } + bool DumpFacebookAppData() const { + return DumpFacebook() || m_fb_app_data.GetOptionValue().GetCurrentValue(); + } + bool DumpFacebookBuildID() const { + return DumpFacebook() || m_fb_build_id.GetOptionValue().GetCurrentValue(); + } + bool DumpFacebookVersionName() const { + return DumpFacebook() || m_fb_version.GetOptionValue().GetCurrentValue(); + } + bool DumpFacebookJavaStack() const { + return DumpFacebook() || m_fb_java_stack.GetOptionValue().GetCurrentValue(); + } + bool DumpFacebookDalvikInfo() const { + return DumpFacebook() || m_fb_dalvik.GetOptionValue().GetCurrentValue(); + } + bool DumpFacebookUnwindSymbols() const { + return DumpFacebook() || m_fb_unwind.GetOptionValue().GetCurrentValue(); + } + bool DumpFacebookErrorLog() const { + return DumpFacebook() || m_fb_error_log.GetOptionValue().GetCurrentValue(); + } + bool DumpFacebookAppStateLog() const { + return DumpFacebook() || m_fb_app_state.GetOptionValue().GetCurrentValue(); + } + bool DumpFacebookAbortReason() const { + return DumpFacebook() || m_fb_abort.GetOptionValue().GetCurrentValue(); + } + bool DumpFacebookThreadName() const { + return DumpFacebook() || m_fb_thread.GetOptionValue().GetCurrentValue(); + } + bool DumpFacebookLogcat() const { + return DumpFacebook() || m_fb_logcat.GetOptionValue().GetCurrentValue(); + } public: - CommandObjectProcessMinidumpDump(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "process plugin dump", - "Dump information from the minidump file.", NULL), + "Dump information from the minidump file.", nullptr), m_option_group(), INIT_BOOL(m_dump_all, "all", 'a', "Dump the everything in the minidump."), @@ -537,7 +629,30 @@ public: INIT_BOOL(m_dump_linux_proc_fd, "fd", 'f', "Dump linux /proc/<pid>/fd."), INIT_BOOL(m_dump_linux_all, "linux", 'l', - "Dump all linux streams.") { + "Dump all linux streams."), + INIT_BOOL(m_fb_app_data, "fb-app-data", 1, + "Dump Facebook application custom data."), + INIT_BOOL(m_fb_build_id, "fb-build-id", 2, + "Dump the Facebook build ID."), + INIT_BOOL(m_fb_version, "fb-version", 3, + "Dump Facebook application version string."), + INIT_BOOL(m_fb_java_stack, "fb-java-stack", 4, + "Dump Facebook java stack."), + INIT_BOOL(m_fb_dalvik, "fb-dalvik-info", 5, + "Dump Facebook Dalvik info."), + INIT_BOOL(m_fb_unwind, "fb-unwind-symbols", 6, + "Dump Facebook unwind symbols."), + INIT_BOOL(m_fb_error_log, "fb-error-log", 7, + "Dump Facebook error log."), + INIT_BOOL(m_fb_app_state, "fb-app-state-log", 8, + "Dump Facebook java stack."), + INIT_BOOL(m_fb_abort, "fb-abort-reason", 9, + "Dump Facebook abort reason."), + INIT_BOOL(m_fb_thread, "fb-thread-name", 10, + "Dump Facebook thread name."), + INIT_BOOL(m_fb_logcat, "fb-logcat", 11, + "Dump Facebook logcat."), + INIT_BOOL(m_fb_all, "facebook", 12, "Dump all Facebook streams.") { APPEND_OPT(m_dump_all); APPEND_OPT(m_dump_directory); APPEND_OPT(m_dump_linux_cpuinfo); @@ -551,10 +666,22 @@ public: APPEND_OPT(m_dump_linux_proc_uptime); APPEND_OPT(m_dump_linux_proc_fd); APPEND_OPT(m_dump_linux_all); + APPEND_OPT(m_fb_app_data); + APPEND_OPT(m_fb_build_id); + APPEND_OPT(m_fb_version); + APPEND_OPT(m_fb_java_stack); + APPEND_OPT(m_fb_dalvik); + APPEND_OPT(m_fb_unwind); + APPEND_OPT(m_fb_error_log); + APPEND_OPT(m_fb_app_state); + APPEND_OPT(m_fb_abort); + APPEND_OPT(m_fb_thread); + APPEND_OPT(m_fb_logcat); + APPEND_OPT(m_fb_all); m_option_group.Finalize(); } - ~CommandObjectProcessMinidumpDump() {} + ~CommandObjectProcessMinidumpDump() override {} Options *GetOptions() override { return &m_option_group; } @@ -572,31 +699,33 @@ public: m_interpreter.GetExecutionContext().GetProcessPtr()); result.SetStatus(eReturnStatusSuccessFinishResult); Stream &s = result.GetOutputStream(); - MinidumpParser &minidump = process->m_minidump_parser; + MinidumpParser &minidump = *process->m_minidump_parser; if (DumpDirectory()) { - s.Printf("RVA SIZE TYPE MinidumpStreamType\n"); + s.Printf("RVA SIZE TYPE StreamType\n"); s.Printf("---------- ---------- ---------- --------------------------\n"); - for (const auto &pair: minidump.GetDirectoryMap()) - s.Printf("0x%8.8x 0x%8.8x 0x%8.8x %s\n", (uint32_t)pair.second.rva, - (uint32_t)pair.second.data_size, pair.first, - MinidumpParser::GetStreamTypeAsString(pair.first).data()); + for (const auto &stream_desc : minidump.GetMinidumpFile().streams()) + s.Printf( + "0x%8.8x 0x%8.8x 0x%8.8x %s\n", (uint32_t)stream_desc.Location.RVA, + (uint32_t)stream_desc.Location.DataSize, + (unsigned)(StreamType)stream_desc.Type, + MinidumpParser::GetStreamTypeAsString(stream_desc.Type).data()); s.Printf("\n"); } - auto DumpTextStream = [&](MinidumpStreamType stream_type, + auto DumpTextStream = [&](StreamType stream_type, llvm::StringRef label) -> void { auto bytes = minidump.GetStream(stream_type); if (!bytes.empty()) { if (label.empty()) - label = MinidumpParser::GetStreamTypeAsString((uint32_t)stream_type); + label = MinidumpParser::GetStreamTypeAsString(stream_type); s.Printf("%s:\n%s\n\n", label.data(), bytes.data()); } }; - auto DumpBinaryStream = [&](MinidumpStreamType stream_type, + auto DumpBinaryStream = [&](StreamType stream_type, llvm::StringRef label) -> void { auto bytes = minidump.GetStream(stream_type); if (!bytes.empty()) { if (label.empty()) - label = MinidumpParser::GetStreamTypeAsString((uint32_t)stream_type); + label = MinidumpParser::GetStreamTypeAsString(stream_type); s.Printf("%s:\n", label.data()); DataExtractor data(bytes.data(), bytes.size(), eByteOrderLittle, process->GetAddressByteSize()); @@ -607,25 +736,67 @@ public: }; if (DumpLinuxCPUInfo()) - DumpTextStream(MinidumpStreamType::LinuxCPUInfo, "/proc/cpuinfo"); + DumpTextStream(StreamType::LinuxCPUInfo, "/proc/cpuinfo"); if (DumpLinuxProcStatus()) - DumpTextStream(MinidumpStreamType::LinuxProcStatus, "/proc/PID/status"); + DumpTextStream(StreamType::LinuxProcStatus, "/proc/PID/status"); if (DumpLinuxLSBRelease()) - DumpTextStream(MinidumpStreamType::LinuxLSBRelease, "/etc/lsb-release"); + DumpTextStream(StreamType::LinuxLSBRelease, "/etc/lsb-release"); if (DumpLinuxCMDLine()) - DumpTextStream(MinidumpStreamType::LinuxCMDLine, "/proc/PID/cmdline"); + DumpTextStream(StreamType::LinuxCMDLine, "/proc/PID/cmdline"); if (DumpLinuxEnviron()) - DumpTextStream(MinidumpStreamType::LinuxEnviron, "/proc/PID/environ"); + DumpTextStream(StreamType::LinuxEnviron, "/proc/PID/environ"); if (DumpLinuxAuxv()) - DumpBinaryStream(MinidumpStreamType::LinuxAuxv, "/proc/PID/auxv"); + DumpBinaryStream(StreamType::LinuxAuxv, "/proc/PID/auxv"); if (DumpLinuxMaps()) - DumpTextStream(MinidumpStreamType::LinuxMaps, "/proc/PID/maps"); + DumpTextStream(StreamType::LinuxMaps, "/proc/PID/maps"); if (DumpLinuxProcStat()) - DumpTextStream(MinidumpStreamType::LinuxProcStat, "/proc/PID/stat"); + DumpTextStream(StreamType::LinuxProcStat, "/proc/PID/stat"); if (DumpLinuxProcUptime()) - DumpTextStream(MinidumpStreamType::LinuxProcUptime, "uptime"); + DumpTextStream(StreamType::LinuxProcUptime, "uptime"); if (DumpLinuxProcFD()) - DumpTextStream(MinidumpStreamType::LinuxProcFD, "/proc/PID/fd"); + DumpTextStream(StreamType::LinuxProcFD, "/proc/PID/fd"); + if (DumpFacebookAppData()) + DumpTextStream(StreamType::FacebookAppCustomData, + "Facebook App Data"); + if (DumpFacebookBuildID()) { + auto bytes = minidump.GetStream(StreamType::FacebookBuildID); + if (bytes.size() >= 4) { + DataExtractor data(bytes.data(), bytes.size(), eByteOrderLittle, + process->GetAddressByteSize()); + lldb::offset_t offset = 0; + uint32_t build_id = data.GetU32(&offset); + s.Printf("Facebook Build ID:\n"); + s.Printf("%u\n", build_id); + s.Printf("\n"); + } + } + if (DumpFacebookVersionName()) + DumpTextStream(StreamType::FacebookAppVersionName, + "Facebook Version String"); + if (DumpFacebookJavaStack()) + DumpTextStream(StreamType::FacebookJavaStack, + "Facebook Java Stack"); + if (DumpFacebookDalvikInfo()) + DumpTextStream(StreamType::FacebookDalvikInfo, + "Facebook Dalvik Info"); + if (DumpFacebookUnwindSymbols()) + DumpBinaryStream(StreamType::FacebookUnwindSymbols, + "Facebook Unwind Symbols Bytes"); + if (DumpFacebookErrorLog()) + DumpTextStream(StreamType::FacebookDumpErrorLog, + "Facebook Error Log"); + if (DumpFacebookAppStateLog()) + DumpTextStream(StreamType::FacebookAppStateLog, + "Faceook Application State Log"); + if (DumpFacebookAbortReason()) + DumpTextStream(StreamType::FacebookAbortReason, + "Facebook Abort Reason"); + if (DumpFacebookThreadName()) + DumpTextStream(StreamType::FacebookThreadName, + "Facebook Thread Name"); + if (DumpFacebookLogcat()) + DumpTextStream(StreamType::FacebookLogcat, + "Facebook Logcat"); return true; } }; @@ -640,12 +811,12 @@ public: CommandObjectSP(new CommandObjectProcessMinidumpDump(interpreter))); } - ~CommandObjectMultiwordProcessMinidump() {} + ~CommandObjectMultiwordProcessMinidump() override {} }; CommandObject *ProcessMinidump::GetPluginCommandObject() { if (!m_command_sp) - m_command_sp.reset(new CommandObjectMultiwordProcessMinidump( - GetTarget().GetDebugger().GetCommandInterpreter())); + m_command_sp = std::make_shared<CommandObjectMultiwordProcessMinidump>( + GetTarget().GetDebugger().GetCommandInterpreter()); return m_command_sp.get(); } |