Allow for empty mapped ranges in mapping files
Bug: 171395772
Bug: 159425023
Bug: 175522004
Change-Id: I8286753f7209dc0906606d661d85f8adc8fb7729
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java b/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
index 43a0511..1fdb08f 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
@@ -98,11 +98,26 @@
CharSource.wrap(contents).openBufferedStream(), diagnosticsHandler);
}
+ public static ClassNameMapper mapperFromString(
+ String contents, DiagnosticsHandler diagnosticsHandler, boolean allowEmptyMappedRanges)
+ throws IOException {
+ return mapperFromBufferedReader(
+ CharSource.wrap(contents).openBufferedStream(), diagnosticsHandler, allowEmptyMappedRanges);
+ }
+
private static ClassNameMapper mapperFromBufferedReader(
BufferedReader reader, DiagnosticsHandler diagnosticsHandler) throws IOException {
+ return mapperFromBufferedReader(reader, diagnosticsHandler, false);
+ }
+
+ private static ClassNameMapper mapperFromBufferedReader(
+ BufferedReader reader, DiagnosticsHandler diagnosticsHandler, boolean allowEmptyMappedRanges)
+ throws IOException {
try (ProguardMapReader proguardReader =
new ProguardMapReader(
- reader, diagnosticsHandler != null ? diagnosticsHandler : new Reporter())) {
+ reader,
+ diagnosticsHandler != null ? diagnosticsHandler : new Reporter(),
+ allowEmptyMappedRanges)) {
ClassNameMapper.Builder builder = ClassNameMapper.builder();
proguardReader.parse(builder);
return builder.build();
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java b/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java
index 28cdcf5..12ea2a6 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java
@@ -458,7 +458,6 @@
private MappedRange(
Range minifiedRange, MethodSignature signature, Object originalRange, String renamedName) {
- assert minifiedRange != null || originalRange == null;
assert originalRange == null
|| originalRange instanceof Integer
|| originalRange instanceof Range;
@@ -510,7 +509,7 @@
builder.append(minifiedRange).append(':');
}
builder.append(signature);
- if (originalRange != null && !minifiedRange.equals(originalRange)) {
+ if (originalRange != null && !originalRange.equals(minifiedRange)) {
builder.append(":").append(originalRange);
}
builder.append(" -> ").append(renamedName);
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java b/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
index 49b46cd..7ddb042 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
@@ -63,15 +63,20 @@
private final BufferedReader reader;
private final JsonParser jsonParser = new JsonParser();
private final DiagnosticsHandler diagnosticsHandler;
+ private final boolean allowEmptyMappedRanges;
@Override
public void close() throws IOException {
reader.close();
}
- ProguardMapReader(BufferedReader reader, DiagnosticsHandler diagnosticsHandler) {
+ ProguardMapReader(
+ BufferedReader reader,
+ DiagnosticsHandler diagnosticsHandler,
+ boolean allowEmptyMappedRanges) {
this.reader = reader;
this.diagnosticsHandler = diagnosticsHandler;
+ this.allowEmptyMappedRanges = allowEmptyMappedRanges;
assert reader != null;
assert diagnosticsHandler != null;
}
@@ -293,7 +298,7 @@
throw new ParseException("No number follows the colon after the method signature.");
}
}
- if (mappedRange == null && originalRange != null) {
+ if (!allowEmptyMappedRanges && mappedRange == null && originalRange != null) {
throw new ParseException("No mapping for original range " + originalRange + ".");
}
diff --git a/src/main/java/com/android/tools/r8/naming/SeedMapper.java b/src/main/java/com/android/tools/r8/naming/SeedMapper.java
index 5c50c06..927cf6e 100644
--- a/src/main/java/com/android/tools/r8/naming/SeedMapper.java
+++ b/src/main/java/com/android/tools/r8/naming/SeedMapper.java
@@ -74,7 +74,7 @@
private static SeedMapper seedMapperFromInputStream(Reporter reporter, InputStream in)
throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
- try (ProguardMapReader proguardReader = new ProguardMapReader(reader, reporter)) {
+ try (ProguardMapReader proguardReader = new ProguardMapReader(reader, reporter, false)) {
SeedMapper.Builder builder = SeedMapper.builder(reporter);
proguardReader.parse(builder);
return builder.build();
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java
index 35f1f63..341ac8d 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java
@@ -124,9 +124,12 @@
private RetracedMethodImpl getRetracedMethod(
MethodReference methodReference, MappedRange mappedRange, int obfuscatedPosition) {
- if (obfuscatedPosition == -1
- || mappedRange.minifiedRange == null
- || !mappedRange.minifiedRange.contains(obfuscatedPosition)) {
+ if (mappedRange.minifiedRange == null) {
+ int originalLineNumber = mappedRange.getFirstLineNumberOfOriginalRange();
+ return RetracedMethodImpl.create(
+ methodReference, originalLineNumber > 0 ? originalLineNumber : obfuscatedPosition);
+ }
+ if (obfuscatedPosition == -1 || !mappedRange.minifiedRange.contains(obfuscatedPosition)) {
return RetracedMethodImpl.create(methodReference);
}
return RetracedMethodImpl.create(
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java
index eed4f28..c2a6749 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java
@@ -32,7 +32,7 @@
}
try {
ClassNameMapper classNameMapper =
- ClassNameMapper.mapperFromString(proguardMapProducer.get(), diagnosticsHandler);
+ ClassNameMapper.mapperFromString(proguardMapProducer.get(), diagnosticsHandler, true);
return new RetracerImpl(classNameMapper);
} catch (Throwable throwable) {
throw new InvalidMappingFileException(throwable);
diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceTests.java b/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
index d23b24e..72221e3 100644
--- a/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
@@ -34,6 +34,7 @@
import com.android.tools.r8.retrace.stacktraces.MemberFieldOverlapStackTrace;
import com.android.tools.r8.retrace.stacktraces.MultipleDotsInFileNameStackTrace;
import com.android.tools.r8.retrace.stacktraces.NamedModuleStackTrace;
+import com.android.tools.r8.retrace.stacktraces.NoObfuscationRangeMappingWithStackTrace;
import com.android.tools.r8.retrace.stacktraces.NullStackTrace;
import com.android.tools.r8.retrace.stacktraces.ObfucatedExceptionClassStackTrace;
import com.android.tools.r8.retrace.stacktraces.ObfuscatedRangeToSingleLineStackTrace;
@@ -94,6 +95,11 @@
}
@Test
+ public void testNoObfuscationRangeMappingWithStackTrace() {
+ runRetraceTest(new NoObfuscationRangeMappingWithStackTrace());
+ }
+
+ @Test
public void testNullLineTrace() {
TestDiagnosticMessagesImpl diagnosticsHandler = new TestDiagnosticMessagesImpl();
NullStackTrace nullStackTrace = new NullStackTrace();
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/NoObfuscationRangeMappingWithStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/NoObfuscationRangeMappingWithStackTrace.java
new file mode 100644
index 0000000..4057a91
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/NoObfuscationRangeMappingWithStackTrace.java
@@ -0,0 +1,47 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace.stacktraces;
+
+import com.android.tools.r8.utils.StringUtils;
+import java.util.Arrays;
+import java.util.List;
+
+public class NoObfuscationRangeMappingWithStackTrace implements StackTraceForTest {
+
+ @Override
+ public List<String> obfuscatedStackTrace() {
+ return Arrays.asList(
+ "Exception in thread \"main\" java.lang.NullPointerException",
+ "\tat foo.a(Bar.dummy:0)",
+ "\tat foo.b(Foo.dummy:2)",
+ "\tat foo.c(Baz.dummy:8)",
+ "\tat foo.d(Qux.dummy:7)");
+ }
+
+ @Override
+ public List<String> retracedStackTrace() {
+ return Arrays.asList(
+ "Exception in thread \"main\" java.lang.NullPointerException",
+ "\tat com.android.tools.r8.naming.retrace.Main.foo(Main.dummy:1)",
+ "\tat com.android.tools.r8.naming.retrace.Main.bar(Main.dummy:3)",
+ "\tat com.android.tools.r8.naming.retrace.Main.baz(Main.dummy:8)",
+ "\tat com.android.tools.r8.naming.retrace.Main.main(Main.dummy:7)");
+ }
+
+ @Override
+ public String mapping() {
+ return StringUtils.lines(
+ "com.android.tools.r8.naming.retrace.Main -> foo:",
+ " void foo(long):1:1 -> a",
+ " void bar(int):3 -> b",
+ " void baz():0:0 -> c", // For 0:0 and 0 use the original line number
+ " void main(java.lang.String[]):0 -> d");
+ }
+
+ @Override
+ public int expectedWarnings() {
+ return 0;
+ }
+}