Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Support debug info in dexmerge and fix max blowup of annotations

Support debug info in dexmerge.

Bug: 4090053

(cherry-pick of bc23c4f.)

Change-Id: I1108933fc03330ff91be3a2edef8b4966977dcd7
Signed-off-by: Jesse Wilson <jesse@swank.ca>

Fix a bug where debugInfos' size wasn't being computed.

Previously debugInfos' size of 0 caused a malformed dex file
because debug data was present but not mentioned in the table
of contents.

Change-Id: I07171aaee12fef9f303fc505909f44ef1a714114

Fix a bug where the max blowup of annotations was incorrect.

I'm not sure where the 1.34 number comes from but it's incorrect.
From the spec, the encoded_annotation is made up of a single byte
plus an unlimited number of uleb128 values. Each of these values
can double in width in the worst case. I received (personal) email
from one user who'd run into a case worse than the incorrect 1.34
limit.

Change-Id: I3b676e6d2b274aaa538ca61ce23945b3d49aff04
  • Loading branch information...
commit 7a9db257544de1f1ab6b99d579142227f700b27d 1 parent c85e122
@enh enh authored elektroschmock committed
View
8 dx/src/com/android/dx/io/DexBuffer.java
@@ -362,6 +362,10 @@ public int readUleb128() {
return Leb128Utils.readUnsignedLeb128(this);
}
+ public int readUleb128p1() {
+ return Leb128Utils.readUnsignedLeb128(this) - 1;
+ }
+
public int readSleb128() {
return Leb128Utils.readSignedLeb128(this);
}
@@ -611,6 +615,10 @@ public void writeUleb128(int i) {
}
}
+ public void writeUleb128p1(int i) {
+ writeUleb128(i + 1);
+ }
+
public void writeSleb128(int i) {
try {
Leb128Utils.writeSignedLeb128(this, i);
View
102 dx/src/com/android/dx/merge/DexMerger.java
@@ -33,9 +33,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
/**
* Combine two dex files into one.
@@ -794,9 +792,13 @@ private void transformCode(DexBuffer in, Code code, IndexMap indexMap) {
Code.Try[] tries = code.getTries();
codeOut.writeUnsignedShort(tries.length);
- // TODO: retain debug info
- // code.getDebugInfoOffset();
- codeOut.writeInt(0);
+ int debugInfoOffset = code.getDebugInfoOffset();
+ if (debugInfoOffset != 0) {
+ codeOut.writeInt(debugInfoOut.getPosition());
+ transformDebugInfoItem(in.open(debugInfoOffset), indexMap);
+ } else {
+ codeOut.writeInt(0);
+ }
short[] instructions = code.getInstructions();
InstructionTransformer transformer = (in == dexA)
@@ -823,6 +825,88 @@ private void transformCode(DexBuffer in, Code code, IndexMap indexMap) {
}
}
+ private static final byte DBG_END_SEQUENCE = 0x00;
+ private static final byte DBG_ADVANCE_PC = 0x01;
+ private static final byte DBG_ADVANCE_LINE = 0x02;
+ private static final byte DBG_START_LOCAL = 0x03;
+ private static final byte DBG_START_LOCAL_EXTENDED = 0x04;
+ private static final byte DBG_END_LOCAL = 0x05;
+ private static final byte DBG_RESTART_LOCAL = 0x06;
+ private static final byte DBG_SET_PROLOGUE_END = 0x07;
+ private static final byte DBG_SET_EPILOGUE_BEGIN = 0x08;
+ private static final byte DBG_SET_FILE = 0x09;
+
+ private void transformDebugInfoItem(DexBuffer.Section in, IndexMap indexMap) {
+ contentsOut.debugInfos.size++;
+ int lineStart = in.readUleb128();
+ debugInfoOut.writeUleb128(lineStart);
+
+ int parametersSize = in.readUleb128();
+ debugInfoOut.writeUleb128(parametersSize);
+
+ for (int p = 0; p < parametersSize; p++) {
+ int parameterName = in.readUleb128p1();
+ debugInfoOut.writeUleb128p1(indexMap.adjustString(parameterName));
+ }
+
+ int addrDiff; // uleb128 address delta.
+ int lineDiff; // sleb128 line delta.
+ int registerNum; // uleb128 register number.
+ int nameIndex; // uleb128p1 string index. Needs indexMap adjustment.
+ int typeIndex; // uleb128p1 type index. Needs indexMap adjustment.
+ int sigIndex; // uleb128p1 string index. Needs indexMap adjustment.
+
+ while (true) {
+ int opcode = in.readByte();
+ debugInfoOut.writeByte(opcode);
+
+ switch (opcode) {
+ case DBG_END_SEQUENCE:
+ return;
+
+ case DBG_ADVANCE_PC:
+ addrDiff = in.readUleb128();
+ debugInfoOut.writeUleb128(addrDiff);
+ break;
+
+ case DBG_ADVANCE_LINE:
+ lineDiff = in.readSleb128();
+ debugInfoOut.writeSleb128(lineDiff);
+ break;
+
+ case DBG_START_LOCAL:
+ case DBG_START_LOCAL_EXTENDED:
+ registerNum = in.readUleb128();
+ debugInfoOut.writeUleb128(registerNum);
+ nameIndex = in.readUleb128p1();
+ debugInfoOut.writeUleb128p1(indexMap.adjustString(nameIndex));
+ typeIndex = in.readUleb128p1();
+ debugInfoOut.writeUleb128p1(indexMap.adjustType(typeIndex));
+ if (opcode == DBG_START_LOCAL_EXTENDED) {
+ sigIndex = in.readUleb128p1();
+ debugInfoOut.writeUleb128p1(indexMap.adjustString(sigIndex));
+ }
+ break;
+
+ case DBG_END_LOCAL:
+ case DBG_RESTART_LOCAL:
+ registerNum = in.readUleb128();
+ debugInfoOut.writeUleb128(registerNum);
+ break;
+
+ case DBG_SET_FILE:
+ nameIndex = in.readUleb128p1();
+ debugInfoOut.writeUleb128p1(indexMap.adjustString(nameIndex));
+ break;
+
+ case DBG_SET_PROLOGUE_END:
+ case DBG_SET_EPILOGUE_BEGIN:
+ default:
+ break;
+ }
+ }
+ }
+
private void transformEncodedCatchHandler(Code.CatchHandler catchHandler, IndexMap indexMap) {
int catchAllAddress = catchHandler.getCatchAllAddress();
int[] typeIndexes = catchHandler.getTypeIndexes();
@@ -910,7 +994,6 @@ public void plus(TableOfContents contents, boolean exact) {
mapList = SizeOf.UINT + (contents.sections.length * SizeOf.MAP_ITEM);
typeList += contents.typeLists.byteCount;
stringData += contents.stringDatas.byteCount;
- debugInfo += contents.debugInfos.byteCount;
annotationsDirectory += contents.annotationsDirectories.byteCount;
annotationsSet += contents.annotationSets.byteCount;
annotationsSetRefList += contents.annotationSetRefLists.byteCount;
@@ -920,6 +1003,7 @@ public void plus(TableOfContents contents, boolean exact) {
classData += contents.classDatas.byteCount;
encodedArray += contents.encodedArrays.byteCount;
annotation += contents.annotations.byteCount;
+ debugInfo += contents.debugInfos.byteCount;
} else {
// at most 1/4 of the bytes in a code section are uleb/sleb
code += (int) Math.ceil(contents.codes.byteCount * 1.25);
@@ -927,8 +1011,10 @@ public void plus(TableOfContents contents, boolean exact) {
classData += (int) Math.ceil(contents.classDatas.byteCount * 1.34);
// all of the bytes in an encoding arrays section may be uleb/sleb
encodedArray += contents.encodedArrays.byteCount * 2;
- // at most 1/3 of the bytes in an encoding arrays section are uleb/sleb
- annotation += (int) Math.ceil(contents.annotations.byteCount * 1.34);
+ // all of the bytes in an annotations section may be uleb/sleb
+ annotation += (int) Math.ceil(contents.annotations.byteCount * 2);
+ // all of the bytes in a debug info section may be uleb/sleb
+ debugInfo += contents.debugInfos.byteCount * 2;
}
typeList = DexBuffer.fourByteAlign(typeList);
Please sign in to comment.
Something went wrong with that request. Please try again.