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



git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@354385 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lit/Minidump/Inputs/fb-dump-content.dmp b/lit/Minidump/Inputs/fb-dump-content.dmp
new file mode 100644
index 0000000..43aaa24
--- /dev/null
+++ b/lit/Minidump/Inputs/fb-dump-content.dmp
Binary files differ
diff --git a/lit/Minidump/fb-dump.test b/lit/Minidump/fb-dump.test
new file mode 100644
index 0000000..3681f8d
--- /dev/null
+++ b/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/source/Plugins/Process/minidump/MinidumpParser.cpp b/source/Plugins/Process/minidump/MinidumpParser.cpp
index 8de7f3a..d2f3b87 100644
--- a/source/Plugins/Process/minidump/MinidumpParser.cpp
+++ b/source/Plugins/Process/minidump/MinidumpParser.cpp
@@ -710,6 +710,17 @@
     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/source/Plugins/Process/minidump/MinidumpTypes.h b/source/Plugins/Process/minidump/MinidumpTypes.h
index b20f50c..47197a3 100644
--- a/source/Plugins/Process/minidump/MinidumpTypes.h
+++ b/source/Plugins/Process/minidump/MinidumpTypes.h
@@ -99,6 +99,18 @@
   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/source/Plugins/Process/minidump/ProcessMinidump.cpp b/source/Plugins/Process/minidump/ProcessMinidump.cpp
index c702d84..c170016 100644
--- a/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -436,10 +436,23 @@
   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 @@
         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 @@
     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 @@
     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);
@@ -550,6 +633,18 @@
     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 @@
       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;
   }
 };