Emit the dex_pc if the line number is absent.

bug:30183883
Test: test-art-host run-libcore-tests run-jdwp-tests
Test: art/test/638-no-line-number/

Change-Id: I5ab54620b2bfba1059543696ff7310b8496b1893
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 7ee0cd1..5d69ca1 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -2484,11 +2484,18 @@
         return nullptr;
       }
       const char* source_file = method->GetDeclaringClassSourceFile();
-      if (source_file != nullptr) {
-        source_name_object.Assign(mirror::String::AllocFromModifiedUtf8(soa.Self(), source_file));
-        if (source_name_object == nullptr) {
-          soa.Self()->AssertPendingOOMException();
-          return nullptr;
+      if (line_number == -1) {
+        // Make the line_number field of StackTraceElement hold the dex pc.
+        // source_name_object is intentionally left null if we failed to map the dex pc to
+        // a line number (most probably because there is no debug info). See b/30183883.
+        line_number = dex_pc;
+      } else {
+        if (source_file != nullptr) {
+          source_name_object.Assign(mirror::String::AllocFromModifiedUtf8(soa.Self(), source_file));
+          if (source_name_object == nullptr) {
+            soa.Self()->AssertPendingOOMException();
+            return nullptr;
+          }
         }
       }
     }
@@ -2499,11 +2506,11 @@
     if (method_name_object == nullptr) {
       return nullptr;
     }
-    ObjPtr<mirror::StackTraceElement> obj =mirror::StackTraceElement::Alloc(soa.Self(),
-                                                                            class_name_object,
-                                                                            method_name_object,
-                                                                            source_name_object,
-                                                                            line_number);
+    ObjPtr<mirror::StackTraceElement> obj = mirror::StackTraceElement::Alloc(soa.Self(),
+                                                                             class_name_object,
+                                                                             method_name_object,
+                                                                             source_name_object,
+                                                                             line_number);
     if (obj == nullptr) {
       return nullptr;
     }
diff --git a/test/638-no-line-number/build b/test/638-no-line-number/build
new file mode 100644
index 0000000..7eaf50e
--- /dev/null
+++ b/test/638-no-line-number/build
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Stop if something fails.
+set -e
+
+mkdir classes
+# Only keep the source name, to make sure we do remove it in the stack trace
+# when there is no line number mapping.
+${JAVAC} -g:source -source 7 -target 7 -d classes `find src -name '*.java'`
+${DX} --dex --output=classes.dex classes
+zip $TEST_NAME.jar classes.dex
diff --git a/test/638-no-line-number/expected.txt b/test/638-no-line-number/expected.txt
new file mode 100644
index 0000000..ffde153
--- /dev/null
+++ b/test/638-no-line-number/expected.txt
@@ -0,0 +1,5 @@
+java.lang.Error
+	at Main.main(Unknown Source:2)
+java.lang.NullPointerException: throw with null exception
+	at Main.doThrow(Unknown Source:0)
+	at Main.main(Unknown Source:9)
diff --git a/test/638-no-line-number/info.txt b/test/638-no-line-number/info.txt
new file mode 100644
index 0000000..89e6432
--- /dev/null
+++ b/test/638-no-line-number/info.txt
@@ -0,0 +1 @@
+Test for b/30183883, that we emit the dex pc when the line number is missing.
diff --git a/test/638-no-line-number/src/Main.java b/test/638-no-line-number/src/Main.java
new file mode 100644
index 0000000..7fe0404
--- /dev/null
+++ b/test/638-no-line-number/src/Main.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+  public static void main(String[] args) {
+    try {
+      doThrow(new Error());
+    } catch (Error e) {
+      e.printStackTrace();
+    }
+    try {
+      doThrow(null);
+    } catch (Throwable t) {
+      t.printStackTrace();
+    }
+  }
+
+  public static void doThrow(Error e) {
+    throw e;
+  }
+}