clayborg created this revision.
clayborg added a reviewer: labath.
Herald added a subscriber: srhines.

SIGSEGV signals are sent to Android processes when a NULL dereference happens 
in Java code that is being run as native code in dex, odex and oat files. In 
this patch I modified the Platforms to be allowed to modify a stop reason for a 
thread. The PlatformAndroid will watch for SIGSEGV stop reasons and see if the 
frame that caused the SIGSEGV comes from a dex, odex or oat file, and if so, it 
will suppress the stop reason. Many IDEs are manually figuring this out and 
learning to skip the signal so users don't see it. Even when IDEs do this, the 
IDE might end up showing a SIGSEGV as a valid stop reason for a thread. Also, a 
SIGSEGV thread might be selected when another thread hits a breakpoint. So we 
suppress these signals to avoid spurious thread changes and improve android 
debugging.


https://reviews.llvm.org/D48177

Files:
  include/lldb/Target/Platform.h
  source/Plugins/Platform/Android/PlatformAndroid.cpp
  source/Plugins/Platform/Android/PlatformAndroid.h
  source/Target/Thread.cpp

Index: source/Target/Thread.cpp
===================================================================
--- source/Target/Thread.cpp
+++ source/Target/Thread.cpp
@@ -439,9 +439,16 @@
     if (m_stop_info_override_stop_id != process_stop_id) {
       m_stop_info_override_stop_id = process_stop_id;
       if (m_stop_info_sp) {
+        // If there is an architecture plug-in for this target architecture,
+        // let it possibly modify the stop reason.
         if (Architecture *arch =
                 process_sp->GetTarget().GetArchitecturePlugin())
           arch->OverrideStopInfo(*this);
+        // Let the platform get a chance to modify the stop reason.
+        auto platform_sp = GetProcess()->GetTarget().GetPlatform();
+        if (platform_sp) {
+          platform_sp->OverrideStopInfo(*this);
+        }
       }
     }
   }
Index: source/Plugins/Platform/Android/PlatformAndroid.h
===================================================================
--- source/Plugins/Platform/Android/PlatformAndroid.h
+++ source/Plugins/Platform/Android/PlatformAndroid.h
@@ -66,6 +66,8 @@
 
   uint32_t GetDefaultMemoryCacheLineSize() override;
 
+  void OverrideStopInfo(Thread &thread) override;
+
 protected:
   const char *GetCacheHostname() override;
 
Index: source/Plugins/Platform/Android/PlatformAndroid.cpp
===================================================================
--- source/Plugins/Platform/Android/PlatformAndroid.cpp
+++ source/Plugins/Platform/Android/PlatformAndroid.cpp
@@ -14,6 +14,9 @@
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Host/StringConvert.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Thread.h"
 #include "lldb/Utility/Log.h"
 #include "lldb/Utility/UriParser.h"
 
@@ -392,11 +395,44 @@
   return PlatformPOSIX::GetLibdlFunctionDeclarations(process);
 }
 
+// Define a SIGSEGV that doesn't require any headers
+#define ANDROID_SIGSEGV 11
+
+void PlatformAndroid::OverrideStopInfo(Thread &thread) {
+  auto stop_info_sp = thread.GetStopInfo();
+  if (!stop_info_sp)
+    return;
+  // Check for SIGSEGV that is called from a .dex, .odex or .oat file.
+  // These are going to be dealt with by the runtime so we can just erase
+  // the stop reason.
+  const auto reason = stop_info_sp->GetStopReason();
+  if (reason != eStopReasonSignal)
+    return;
+  if (stop_info_sp->GetValue() != ANDROID_SIGSEGV)
+    return;
+  auto frame_sp = thread.GetStackFrameAtIndex(0);
+  if (!frame_sp)
+    return;
+  auto module_sp = frame_sp->GetSymbolContext(eSymbolContextModule).module_sp;
+  if (!module_sp)
+    return;
+  auto ext = module_sp->GetFileSpec().GetFileNameExtension();
+  if (!ext)
+    return;
+  llvm::StringRef ext_ref(ext.GetCString(), ext.GetLength());
+  // We are lookking for .dex, .odex, and .oat files.
+  if (ext_ref.endswith("dex") || ext_ref.endswith("oat")) {
+    // We have a SIGSEGV we need to mute
+    thread.SetStopInfo(lldb::StopInfoSP());
+  }
+}
+
 AdbClient::SyncService *PlatformAndroid::GetSyncService(Status &error) {
   if (m_adb_sync_svc && m_adb_sync_svc->IsConnected())
     return m_adb_sync_svc.get();
 
   AdbClient adb(m_device_id);
   m_adb_sync_svc = adb.GetSyncService(error);
   return (error.Success()) ? m_adb_sync_svc.get() : nullptr;
 }
+
Index: include/lldb/Target/Platform.h
===================================================================
--- include/lldb/Target/Platform.h
+++ include/lldb/Target/Platform.h
@@ -858,6 +858,16 @@
   virtual size_t ConnectToWaitingProcesses(lldb_private::Debugger &debugger,
                                            lldb_private::Status &error);
 
+  //------------------------------------------------------------------
+  /// Allow platforms to modify thread stop info.
+  ///
+  /// Platforms might have specific signals or stop reasons that are
+  /// overloaded and might not need to be reported. Platform
+  /// subclasses can override this function and modify the stop reason
+  /// when needed.
+  //------------------------------------------------------------------
+  virtual void OverrideStopInfo(Thread &thread) {}
+
 protected:
   bool m_is_host;
   // Set to true when we are able to actually set the OS version while being
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to