From cc6ec692a4f5202c4613dcef74d36682dca93241 Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Tue, 19 Feb 2019 21:48:34 +0000 Subject: [PATCH] Add Facebook Minidump directory streams and options to dump them. Facebook creates minidump files that contain specific information about why things crash. Adding ways to dump these allows tools to be made that can auto download symbols based on the information that is contained in the minidump files. Differential Revision: https://reviews.llvm.org/D58398 llvm-svn: 354385 --- lldb/lit/Minidump/Inputs/fb-dump-content.dmp | Bin 0 -> 511 bytes lldb/lit/Minidump/fb-dump.test | 105 +++++++++++++ .../Process/minidump/MinidumpParser.cpp | 11 ++ .../Plugins/Process/minidump/MinidumpTypes.h | 12 ++ .../Process/minidump/ProcessMinidump.cpp | 141 +++++++++++++++++- 5 files changed, 267 insertions(+), 2 deletions(-) create mode 100644 lldb/lit/Minidump/Inputs/fb-dump-content.dmp create mode 100644 lldb/lit/Minidump/fb-dump.test diff --git a/lldb/lit/Minidump/Inputs/fb-dump-content.dmp b/lldb/lit/Minidump/Inputs/fb-dump-content.dmp new file mode 100644 index 0000000000000000000000000000000000000000..43aaa24dd6b8adeede51708f043580bdd48e51d9 GIT binary patch literal 511 zcmaiv%SyvQ6oyZ&;-;b^-av5314yk}YuB;6f_qofWE#iDOq_;nN}>1)K14wfU!YH* zB|Ep`+Kn4m+T1s`8&{}EcE02Dx=tK+dvVfn7%tVL7 zqioH?kaZ&-iNAY!OX-MVe^&+6vpiq5xNp^2&uYlP6FSr~h^)FLgP8l$Wv+;&BUt-a zvEQfZ;#7eu<^8Sl_o!8~drx`H(~F%BlR;Z$1(*A=oS2K&j!h+ed7Jj=kSfSk`T`d? BeqI0o literal 0 HcmV?d00001 diff --git a/lldb/lit/Minidump/fb-dump.test b/lldb/lit/Minidump/fb-dump.test new file mode 100644 index 000000000000..3681f8dbbd72 --- /dev/null +++ b/lldb/lit/Minidump/fb-dump.test @@ -0,0 +1,105 @@ +# RUN: %lldb -c %p/Inputs/fb-dump-content.dmp \ +# RUN: -o 'process plugin dump --all' | \ +# RUN: FileCheck --check-prefix=CHECK-DIR --check-prefix=CHECK-APPDATA \ +# RUN: --check-prefix=CHECK-BUILD --check-prefix=CHECK-VERSION \ +# RUN: --check-prefix=CHECK-JAVA --check-prefix=CHECK-DALVIK \ +# RUN: --check-prefix=CHECK-UNWIND --check-prefix=CHECK-ERROR \ +# RUN: --check-prefix=CHECK-APPSTATE --check-prefix=CHECK-ABORT \ +# RUN: --check-prefix=CHECK-THREAD --check-prefix=CHECK-LOGCAT %s +# RUN: %lldb -c %p/Inputs/fb-dump-content.dmp \ +# RUN: -o 'process plugin dump -a' | \ +# RUN: FileCheck --check-prefix=CHECK-DIR --check-prefix=CHECK-APPDATA \ +# RUN: --check-prefix=CHECK-BUILD --check-prefix=CHECK-VERSION \ +# RUN: --check-prefix=CHECK-JAVA --check-prefix=CHECK-DALVIK \ +# RUN: --check-prefix=CHECK-UNWIND --check-prefix=CHECK-ERROR \ +# RUN: --check-prefix=CHECK-APPSTATE --check-prefix=CHECK-ABORT \ +# RUN: --check-prefix=CHECK-THREAD --check-prefix=CHECK-LOGCAT %s +# RUN: %lldb -c %p/Inputs/fb-dump-content.dmp \ +# RUN: -o 'process plugin dump --facebook' | \ +# RUN: FileCheck --check-prefix=CHECK-APPDATA \ +# RUN: --check-prefix=CHECK-BUILD --check-prefix=CHECK-VERSION \ +# RUN: --check-prefix=CHECK-JAVA --check-prefix=CHECK-DALVIK \ +# RUN: --check-prefix=CHECK-UNWIND --check-prefix=CHECK-ERROR \ +# RUN: --check-prefix=CHECK-APPSTATE --check-prefix=CHECK-ABORT \ +# RUN: --check-prefix=CHECK-THREAD --check-prefix=CHECK-LOGCAT %s +# RUN: %lldb -c %p/Inputs/fb-dump-content.dmp \ +# RUN: -o 'process plugin dump --fb-app-data' | \ +# RUN: FileCheck --check-prefix=CHECK-APPDATA %s +# RUN: %lldb -c %p/Inputs/fb-dump-content.dmp \ +# RUN: -o 'process plugin dump --fb-build-id' | \ +# RUN: FileCheck --check-prefix=CHECK-BUILD %s +# RUN: %lldb -c %p/Inputs/fb-dump-content.dmp \ +# RUN: -o 'process plugin dump --fb-version' | \ +# RUN: FileCheck --check-prefix=CHECK-VERSION %s +# RUN: %lldb -c %p/Inputs/fb-dump-content.dmp \ +# RUN: -o 'process plugin dump --fb-java-stack' | \ +# RUN: FileCheck --check-prefix=CHECK-JAVA %s +# RUN: %lldb -c %p/Inputs/fb-dump-content.dmp \ +# RUN: -o 'process plugin dump --fb-dalvik-info' | \ +# RUN: FileCheck --check-prefix=CHECK-DALVIK %s +# RUN: %lldb -c %p/Inputs/fb-dump-content.dmp \ +# RUN: -o 'process plugin dump --fb-unwind-symbols' | \ +# RUN: FileCheck --check-prefix=CHECK-UNWIND %s +# RUN: %lldb -c %p/Inputs/fb-dump-content.dmp \ +# RUN: -o 'process plugin dump --fb-error-log' | \ +# RUN: FileCheck --check-prefix=CHECK-ERROR %s +# RUN: %lldb -c %p/Inputs/fb-dump-content.dmp \ +# RUN: -o 'process plugin dump --fb-app-state-log' | \ +# RUN: FileCheck --check-prefix=CHECK-APPSTATE %s +# RUN: %lldb -c %p/Inputs/fb-dump-content.dmp \ +# RUN: -o 'process plugin dump --fb-abort-reason' | \ +# RUN: FileCheck --check-prefix=CHECK-ABORT %s +# RUN: %lldb -c %p/Inputs/fb-dump-content.dmp \ +# RUN: -o 'process plugin dump --fb-thread-name' | \ +# RUN: FileCheck --check-prefix=CHECK-THREAD %s +# RUN: %lldb -c %p/Inputs/fb-dump-content.dmp \ +# RUN: -o 'process plugin dump --fb-logcat' | \ +# RUN: FileCheck --check-prefix=CHECK-LOGCAT %s +# CHECK-DIR: RVA SIZE TYPE MinidumpStreamType +# CHECK-DIR-NEXT: ---------- ---------- ---------- -------------------------- +# CHECK-DIR-NEXT: 0x0000010c 0x00000013 0xfacecb00 FacebookDumpErrorLog +# CHECK-DIR-NEXT: 0x0000011f 0x00000015 0xfacee000 FacebookThreadName +# CHECK-DIR-NEXT: 0x0000015b 0x00000016 0xfacedead FacebookAbortReason +# CHECK-DIR-NEXT: 0x000000bc 0x00000038 0x00000007 SystemInfo +# CHECK-DIR-NEXT: 0x000001aa 0x00000005 0xfacecafb FacebookBuildID +# CHECK-DIR-NEXT: 0x000001bc 0x00000019 0xfacecafd FacebookJavaStack +# CHECK-DIR-NEXT: 0x000001ea 0x00000005 0xfacecaff FacebookUnwindSymbols +# CHECK-DIR-NEXT: 0x00000171 0x00000039 0xfacecafa FacebookAppCustomData +# CHECK-DIR-NEXT: 0x00000134 0x00000010 0xface1ca7 FacebookLogcat +# CHECK-DIR-NEXT: 0x000000f4 0x00000018 0x0000000f MiscInfo +# CHECK-DIR-NEXT: 0x000001af 0x0000000d 0xfacecafc FacebookAppVersionName +# CHECK-DIR-NEXT: 0x000001d5 0x00000015 0xfacecafe FacebookDalvikInfo +# CHECK-DIR-NEXT: 0x00000144 0x00000017 0xfacecccc FacebookAppStateLog + +# CHECK-APPDATA: Facebook App Data: +# CHECK-APPDATA-NEXT: {"global": {"Fingerprint":"invalid device fingerprint"}} + +# CHECK-BUILD: Facebook Build ID: +# CHECK-BUILD-NEXT: 16909060 + +# CHECK-VERSION: Facebook Version String: +# CHECK-VERSION-NEXT: 207.0.0.0.86 + +# CHECK-JAVA: Facebook Java Stack: +# CHECK-JAVA-NEXT: Facebook java stack info + +# CHECK-DALVIK: Facebook Dalvik Info: +# CHECK-DALVIK-NEXT: Facebook dalvik info + +# CHECK-UNWIND: Facebook Unwind Symbols Bytes: +# CHECK-UNWIND-NEXT: 0x00000000: 11 22 33 44 00 + +# CHECK-ERROR: Facebook Error Log: +# CHECK-ERROR-NEXT: Facebook error log + +# CHECK-APPSTATE: Faceook Application State Log: +# CHECK-APPSTATE-NEXT: Facebook app state log + +# CHECK-ABORT: Facebook Abort Reason: +# CHECK-ABORT-NEXT: Facebook abort reason + +# CHECK-THREAD: Facebook Thread Name: +# CHECK-THREAD-NEXT: Facebook thread name + +# CHECK-LOGCAT: Facebook Logcat: +# CHECK-LOGCAT-NEXT: Facebook logcat diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp index 8de7f3ae98f1..d2f3b87a4ae4 100644 --- a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp +++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp @@ -710,6 +710,17 @@ MinidumpParser::GetStreamTypeAsString(uint32_t stream_type) { ENUM_TO_CSTR(LinuxProcStat); ENUM_TO_CSTR(LinuxProcUptime); ENUM_TO_CSTR(LinuxProcFD); + ENUM_TO_CSTR(FacebookAppCustomData); + ENUM_TO_CSTR(FacebookBuildID); + ENUM_TO_CSTR(FacebookAppVersionName); + ENUM_TO_CSTR(FacebookJavaStack); + ENUM_TO_CSTR(FacebookDalvikInfo); + ENUM_TO_CSTR(FacebookUnwindSymbols); + ENUM_TO_CSTR(FacebookDumpErrorLog); + ENUM_TO_CSTR(FacebookAppStateLog); + ENUM_TO_CSTR(FacebookAbortReason); + ENUM_TO_CSTR(FacebookThreadName); + ENUM_TO_CSTR(FacebookLogcat); } return "unknown stream type"; } diff --git a/lldb/source/Plugins/Process/minidump/MinidumpTypes.h b/lldb/source/Plugins/Process/minidump/MinidumpTypes.h index b20f50cadd6f..47197a31a568 100644 --- a/lldb/source/Plugins/Process/minidump/MinidumpTypes.h +++ b/lldb/source/Plugins/Process/minidump/MinidumpTypes.h @@ -99,6 +99,18 @@ enum class MinidumpStreamType : uint32_t { LinuxProcStat = 0x4767000B, /* /proc/$x/stat */ LinuxProcUptime = 0x4767000C, /* uptime */ LinuxProcFD = 0x4767000D, /* /proc/$x/fb */ + FacebookAppCustomData = 0xFACECAFA, + FacebookBuildID = 0xFACECAFB, + FacebookAppVersionName = 0xFACECAFC, + FacebookJavaStack = 0xFACECAFD, + FacebookDalvikInfo = 0xFACECAFE, + FacebookUnwindSymbols = 0xFACECAFF, + FacebookDumpErrorLog = 0xFACECB00, + FacebookAppStateLog = 0xFACECCCC, + FacebookAbortReason = 0xFACEDEAD, + FacebookThreadName = 0xFACEE000, + FacebookLogcat = 0xFACE1CA7, + }; // for MinidumpSystemInfo.processor_arch diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp index c702d843809e..c17001634f1b 100644 --- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp +++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -436,10 +436,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() || @@ -450,7 +463,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); @@ -505,6 +529,42 @@ 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) @@ -536,7 +596,30 @@ public: INIT_BOOL(m_dump_linux_proc_fd, "fd", 'f', "Dump linux /proc//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); @@ -550,6 +633,18 @@ 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(); } @@ -625,6 +720,48 @@ public: DumpTextStream(MinidumpStreamType::LinuxProcUptime, "uptime"); if (DumpLinuxProcFD()) DumpTextStream(MinidumpStreamType::LinuxProcFD, "/proc/PID/fd"); + if (DumpFacebookAppData()) + DumpTextStream(MinidumpStreamType::FacebookAppCustomData, + "Facebook App Data"); + if (DumpFacebookBuildID()) { + auto bytes = minidump.GetStream(MinidumpStreamType::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(MinidumpStreamType::FacebookAppVersionName, + "Facebook Version String"); + if (DumpFacebookJavaStack()) + DumpTextStream(MinidumpStreamType::FacebookJavaStack, + "Facebook Java Stack"); + if (DumpFacebookDalvikInfo()) + DumpTextStream(MinidumpStreamType::FacebookDalvikInfo, + "Facebook Dalvik Info"); + if (DumpFacebookUnwindSymbols()) + DumpBinaryStream(MinidumpStreamType::FacebookUnwindSymbols, + "Facebook Unwind Symbols Bytes"); + if (DumpFacebookErrorLog()) + DumpTextStream(MinidumpStreamType::FacebookDumpErrorLog, + "Facebook Error Log"); + if (DumpFacebookAppStateLog()) + DumpTextStream(MinidumpStreamType::FacebookAppStateLog, + "Faceook Application State Log"); + if (DumpFacebookAbortReason()) + DumpTextStream(MinidumpStreamType::FacebookAbortReason, + "Facebook Abort Reason"); + if (DumpFacebookThreadName()) + DumpTextStream(MinidumpStreamType::FacebookThreadName, + "Facebook Thread Name"); + if (DumpFacebookLogcat()) + DumpTextStream(MinidumpStreamType::FacebookLogcat, + "Facebook Logcat"); return true; } };