Skip to content

Commit

Permalink
Support debug info in dexmerge and fix max blowup of annotations
Browse files Browse the repository at this point in the history
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
enh-google authored and elektroschmock committed Sep 6, 2012
1 parent c85e122 commit 7a9db25
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 8 deletions.
8 changes: 8 additions & 0 deletions dx/src/com/android/dx/io/DexBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down
102 changes: 94 additions & 8 deletions dx/src/com/android/dx/merge/DexMerger.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand All @@ -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();
Expand Down Expand Up @@ -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;
Expand All @@ -920,15 +1003,18 @@ 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);
// at most 1/3 of the bytes in a class data section are uleb/sleb
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);
Expand Down

0 comments on commit 7a9db25

Please sign in to comment.