mirror of
https://github.com/revanced/smali.git
synced 2025-05-16 22:17:07 +02:00
- changed the syntax for the .catch directive, to get rid of "from", "to" and "using" (too visual basicy)
- added support for the .local directive, which allows you to define a local variable in the debug info (no way to undefine it until ".end local" is implemented) git-svn-id: https://smali.googlecode.com/svn/trunk@46 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
parent
66a23e6ecc
commit
f175e1d987
@ -457,11 +457,11 @@ CATCH_PHRASE
|
|||||||
: CATCH_DIRECTIVE_EMIT
|
: CATCH_DIRECTIVE_EMIT
|
||||||
WS
|
WS
|
||||||
FIELD_TYPE_DESCRIPTOR_EMITCHILD
|
FIELD_TYPE_DESCRIPTOR_EMITCHILD
|
||||||
WS 'from' WS
|
WS? '{' WS?
|
||||||
(LABEL_EMIT | OFFSET_EMIT)
|
(LABEL_EMIT | OFFSET_EMIT)
|
||||||
WS 'to' WS
|
WS '..' WS
|
||||||
(LABEL_EMIT | OFFSET_EMIT)
|
(LABEL_EMIT | OFFSET_EMIT)
|
||||||
WS 'using' WS
|
WS? '}' WS?
|
||||||
(LABEL_EMIT | OFFSET_EMIT);
|
(LABEL_EMIT | OFFSET_EMIT);
|
||||||
|
|
||||||
LINE_PHRASE
|
LINE_PHRASE
|
||||||
@ -472,6 +472,15 @@ LINE_PHRASE
|
|||||||
PARAMETER_PHRASE
|
PARAMETER_PHRASE
|
||||||
: PARAMETER_DIRECTIVE_EMIT
|
: PARAMETER_DIRECTIVE_EMIT
|
||||||
(WS STRING_LITERAL_EMIT?)?;
|
(WS STRING_LITERAL_EMIT?)?;
|
||||||
|
|
||||||
|
LOCAL_PHRASE
|
||||||
|
: LOCAL_DIRECTIVE_EMIT
|
||||||
|
WS
|
||||||
|
REGISTER_EMIT
|
||||||
|
WS? ',' WS?
|
||||||
|
SIMPLE_NAME_EMIT
|
||||||
|
WS
|
||||||
|
FIELD_TYPE_DESCRIPTOR_EMITCHILD;
|
||||||
|
|
||||||
|
|
||||||
//TODO: add support for both relative and absolute offsets?
|
//TODO: add support for both relative and absolute offsets?
|
||||||
@ -569,11 +578,16 @@ fragment PARAMETER_DIRECTIVE_EMIT
|
|||||||
: PARAMETER_DIRECTIVE {emit($PARAMETER_DIRECTIVE, PARAMETER_DIRECTIVE);};
|
: PARAMETER_DIRECTIVE {emit($PARAMETER_DIRECTIVE, PARAMETER_DIRECTIVE);};
|
||||||
fragment PARAMETER_DIRECTIVE
|
fragment PARAMETER_DIRECTIVE
|
||||||
: '.parameter';
|
: '.parameter';
|
||||||
|
|
||||||
|
fragment LOCAL_DIRECTIVE_EMIT
|
||||||
|
: LOCAL_DIRECTIVE {emit($LOCAL_DIRECTIVE, LOCAL_DIRECTIVE);};
|
||||||
|
fragment LOCAL_DIRECTIVE
|
||||||
|
: '.local';
|
||||||
|
|
||||||
fragment REGISTER_EMIT
|
fragment REGISTER_EMIT
|
||||||
: REGISTER {emit($REGISTER, REGISTER);};
|
: REGISTER {emit($REGISTER, REGISTER);};
|
||||||
fragment REGISTER
|
fragment REGISTER
|
||||||
: 'v' ('0'..'9')+;
|
: 'v' ('0'..'9')+;
|
||||||
|
|
||||||
fragment REGISTER_LIST_EMITCHILDREN
|
fragment REGISTER_LIST_EMITCHILDREN
|
||||||
: OPEN_BRACKET_EMIT
|
: OPEN_BRACKET_EMIT
|
||||||
@ -720,6 +734,8 @@ fragment MEMBER_NAME_EMIT
|
|||||||
fragment MEMBER_NAME
|
fragment MEMBER_NAME
|
||||||
: '<'? SIMPLE_NAME '>'?;
|
: '<'? SIMPLE_NAME '>'?;
|
||||||
|
|
||||||
|
fragment SIMPLE_NAME_EMIT
|
||||||
|
: SIMPLE_NAME {emit($SIMPLE_NAME, SIMPLE_NAME);};
|
||||||
|
|
||||||
fragment SIMPLE_NAME:
|
fragment SIMPLE_NAME:
|
||||||
( 'A'..'Z'
|
( 'A'..'Z'
|
||||||
|
@ -62,14 +62,15 @@ tokens {
|
|||||||
I_SPARSE_SWITCH_KEYS;
|
I_SPARSE_SWITCH_KEYS;
|
||||||
I_SPARSE_SWITCH_TARGET_COUNT;
|
I_SPARSE_SWITCH_TARGET_COUNT;
|
||||||
I_SPARSE_SWITCH_TARGETS;
|
I_SPARSE_SWITCH_TARGETS;
|
||||||
|
I_ADDRESS;
|
||||||
I_CATCH;
|
I_CATCH;
|
||||||
I_CATCHES;
|
I_CATCHES;
|
||||||
I_CATCH_ADDRESS;
|
|
||||||
I_LINE;
|
|
||||||
I_LINES;
|
|
||||||
I_PARAMETER;
|
I_PARAMETER;
|
||||||
I_PARAMETERS;
|
I_PARAMETERS;
|
||||||
I_PARAMETER_NOT_SPECIFIED;
|
I_PARAMETER_NOT_SPECIFIED;
|
||||||
|
I_ORDERED_DEBUG_DIRECTIVES;
|
||||||
|
I_LINE;
|
||||||
|
I_LOCAL;
|
||||||
I_STATEMENTS;
|
I_STATEMENTS;
|
||||||
I_STATEMENT_FORMAT10t;
|
I_STATEMENT_FORMAT10t;
|
||||||
I_STATEMENT_FORMAT10x;
|
I_STATEMENT_FORMAT10x;
|
||||||
@ -216,10 +217,11 @@ statements_and_directives
|
|||||||
}
|
}
|
||||||
( instruction {$method::currentAddress += $instruction.size/2;}
|
( instruction {$method::currentAddress += $instruction.size/2;}
|
||||||
| {!hasRegistersDirective}?=> registers_directive {hasRegistersDirective = true;}
|
| {!hasRegistersDirective}?=> registers_directive {hasRegistersDirective = true;}
|
||||||
|
| label
|
||||||
| catch_directive
|
| catch_directive
|
||||||
| line_directive
|
|
||||||
| parameter_directive
|
| parameter_directive
|
||||||
| label)*
|
| ordered_debug_directive
|
||||||
|
)*
|
||||||
{
|
{
|
||||||
if (!hasRegistersDirective) {
|
if (!hasRegistersDirective) {
|
||||||
//TODO: throw correct exception type here
|
//TODO: throw correct exception type here
|
||||||
@ -230,8 +232,8 @@ statements_and_directives
|
|||||||
^(I_LABELS label*)
|
^(I_LABELS label*)
|
||||||
^(I_STATEMENTS instruction*)
|
^(I_STATEMENTS instruction*)
|
||||||
^(I_CATCHES catch_directive*)
|
^(I_CATCHES catch_directive*)
|
||||||
^(I_LINES line_directive*)
|
^(I_PARAMETERS parameter_directive*)
|
||||||
^(I_PARAMETERS parameter_directive*);
|
^(I_ORDERED_DEBUG_DIRECTIVES ordered_debug_directive*);
|
||||||
|
|
||||||
registers_directive
|
registers_directive
|
||||||
: REGISTERS_DIRECTIVE integral_literal
|
: REGISTERS_DIRECTIVE integral_literal
|
||||||
@ -239,19 +241,28 @@ registers_directive
|
|||||||
|
|
||||||
catch_directive
|
catch_directive
|
||||||
: CATCH_DIRECTIVE field_type_descriptor from=offset_or_label to=offset_or_label using=offset_or_label
|
: CATCH_DIRECTIVE field_type_descriptor from=offset_or_label to=offset_or_label using=offset_or_label
|
||||||
-> ^(I_CATCH[$start, "I_CATCH"] I_CATCH_ADDRESS[$start, Integer.toString($method::currentAddress)] field_type_descriptor $from $to $using)
|
-> ^(I_CATCH[$start, "I_CATCH"] I_ADDRESS[$start, Integer.toString($method::currentAddress)] field_type_descriptor $from $to $using)
|
||||||
;
|
;
|
||||||
|
|
||||||
line_directive
|
|
||||||
: LINE_DIRECTIVE integral_literal -> ^(I_LINE integral_literal {new CommonTree(new CommonToken(INTEGER_LITERAL,Integer.toString($method::currentAddress)))});
|
|
||||||
|
|
||||||
parameter_directive
|
parameter_directive
|
||||||
: PARAMETER_DIRECTIVE ( STRING_LITERAL -> ^(I_PARAMETER STRING_LITERAL?)
|
: PARAMETER_DIRECTIVE ( STRING_LITERAL -> ^(I_PARAMETER STRING_LITERAL?)
|
||||||
| -> ^(I_PARAMETER I_PARAMETER_NOT_SPECIFIED)
|
| -> ^(I_PARAMETER I_PARAMETER_NOT_SPECIFIED)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ordered_debug_directive
|
||||||
|
: line_directive
|
||||||
|
| local_directive;
|
||||||
|
|
||||||
|
line_directive
|
||||||
|
: LINE_DIRECTIVE integral_literal -> ^(I_LINE integral_literal I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
|
||||||
|
|
||||||
|
local_directive
|
||||||
|
: LOCAL_DIRECTIVE REGISTER SIMPLE_NAME field_type_descriptor
|
||||||
|
-> ^(I_LOCAL[$start, "I_LOCAL"] REGISTER SIMPLE_NAME field_type_descriptor I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
|
||||||
|
|
||||||
label
|
label
|
||||||
: LABEL -> ^(I_LABEL LABEL {new CommonTree(new CommonToken(INTEGER_LITERAL,Integer.toString($method::currentAddress)))});
|
: LABEL -> ^(I_LABEL LABEL I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
|
||||||
|
|
||||||
instruction returns [int size]
|
instruction returns [int size]
|
||||||
@init {boolean needsNop = false;}
|
@init {boolean needsNop = false;}
|
||||||
|
@ -82,7 +82,7 @@ import org.JesusFreke.dexlib.code.Format.*;
|
|||||||
}
|
}
|
||||||
//the parser wouldn't accept a negative register, i.e. v-1, so we don't have to check for val<0;
|
//the parser wouldn't accept a negative register, i.e. v-1, so we don't have to check for val<0;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -301,8 +301,9 @@ method returns[ClassDataItem.EncodedMethod encodedMethod]
|
|||||||
labels
|
labels
|
||||||
statements
|
statements
|
||||||
catches
|
catches
|
||||||
lines
|
parameters
|
||||||
parameters)
|
ordered_debug_directives
|
||||||
|
)
|
||||||
{
|
{
|
||||||
MethodIdItem methodIdItem = $method_name_and_prototype.methodIdItem;
|
MethodIdItem methodIdItem = $method_name_and_prototype.methodIdItem;
|
||||||
int registers = $registers_directive.registers;
|
int registers = $registers_directive.registers;
|
||||||
@ -400,42 +401,11 @@ fully_qualified_field returns[FieldIdItem fieldIdItem]
|
|||||||
registers_directive returns[int registers]
|
registers_directive returns[int registers]
|
||||||
: ^(I_REGISTERS short_integral_literal) {$registers = $short_integral_literal.value;};
|
: ^(I_REGISTERS short_integral_literal) {$registers = $short_integral_literal.value;};
|
||||||
|
|
||||||
catches : ^(I_CATCHES catch_directive*);
|
|
||||||
|
|
||||||
catch_directive
|
|
||||||
: ^(I_CATCH I_CATCH_ADDRESS field_type_descriptor from=offset_or_label to=offset_or_label using=offset_or_label)
|
|
||||||
{
|
|
||||||
TypeIdItem type = $field_type_descriptor.type;
|
|
||||||
int startAddress = $from.offsetValue + $method::currentAddress;
|
|
||||||
int endAddress = $to.offsetValue + $method::currentAddress;
|
|
||||||
int handlerAddress = $using.offsetValue + $method::currentAddress;
|
|
||||||
|
|
||||||
$method::tryList.addHandler(type, startAddress, endAddress, handlerAddress);
|
|
||||||
};
|
|
||||||
|
|
||||||
lines
|
|
||||||
: ^(I_LINES line*);
|
|
||||||
|
|
||||||
line
|
|
||||||
: ^(I_LINE integral_literal integer_literal)
|
|
||||||
{
|
|
||||||
$method::debugInfo.addLine($integer_literal.value, $integral_literal.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
parameters
|
|
||||||
: ^(I_PARAMETERS parameter*);
|
|
||||||
|
|
||||||
parameter
|
|
||||||
: ^(I_PARAMETER (
|
|
||||||
string_literal {$method::debugInfo.addParameterName($string_literal.value);}
|
|
||||||
| I_PARAMETER_NOT_SPECIFIED {$method::debugInfo.addParameterName(null);}
|
|
||||||
));
|
|
||||||
|
|
||||||
labels
|
labels
|
||||||
: ^(I_LABELS label_def*);
|
: ^(I_LABELS label_def*);
|
||||||
|
|
||||||
label_def
|
label_def
|
||||||
: ^(I_LABEL label integer_literal)
|
: ^(I_LABEL label address)
|
||||||
{
|
{
|
||||||
String labelName = $label.labelName;
|
String labelName = $label.labelName;
|
||||||
if ($method::labels.containsKey(labelName)) {
|
if ($method::labels.containsKey(labelName)) {
|
||||||
@ -444,8 +414,55 @@ label_def
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$method::labels.put(labelName, $integer_literal.value);
|
$method::labels.put(labelName, $address.address);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
catches : ^(I_CATCHES catch_directive*);
|
||||||
|
|
||||||
|
catch_directive
|
||||||
|
: ^(I_CATCH address field_type_descriptor from=offset_or_label_absolute[$address.address] to=offset_or_label_absolute[$address.address] using=offset_or_label_absolute[$address.address])
|
||||||
|
{
|
||||||
|
TypeIdItem type = $field_type_descriptor.type;
|
||||||
|
int startAddress = $from.address;
|
||||||
|
int endAddress = $to.address;
|
||||||
|
int handlerAddress = $using.address;
|
||||||
|
|
||||||
|
$method::tryList.addHandler(type, startAddress, endAddress, handlerAddress);
|
||||||
|
};
|
||||||
|
|
||||||
|
address returns[int address]
|
||||||
|
: I_ADDRESS
|
||||||
|
{
|
||||||
|
$address = Integer.parseInt($I_ADDRESS.text);
|
||||||
|
};
|
||||||
|
|
||||||
|
parameters
|
||||||
|
: ^(I_PARAMETERS parameter*);
|
||||||
|
|
||||||
|
parameter
|
||||||
|
: ^(I_PARAMETER (
|
||||||
|
string_literal {$method::debugInfo.addParameterName($string_literal.value);}
|
||||||
|
| I_PARAMETER_NOT_SPECIFIED {$method::debugInfo.addParameterName(null);}
|
||||||
|
));
|
||||||
|
|
||||||
|
ordered_debug_directives
|
||||||
|
: ^(I_ORDERED_DEBUG_DIRECTIVES (line | local)*);
|
||||||
|
|
||||||
|
line
|
||||||
|
: ^(I_LINE integral_literal address)
|
||||||
|
{
|
||||||
|
$method::debugInfo.addLine($address.address, $integral_literal.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
local : ^(I_LOCAL REGISTER SIMPLE_NAME field_type_descriptor address)
|
||||||
|
{
|
||||||
|
|
||||||
|
int registerNumber = parseRegister_short($REGISTER.text);
|
||||||
|
|
||||||
|
$method::debugInfo.addLocal($address.address, registerNumber, $SIMPLE_NAME.text, $field_type_descriptor.type.toString());
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
statements returns[ArrayList<Instruction> instructions]
|
statements returns[ArrayList<Instruction> instructions]
|
||||||
@init
|
@init
|
||||||
@ -488,15 +505,13 @@ offset returns[int offsetValue]
|
|||||||
$offsetValue = literalTools.parseInt(offsetText);
|
$offsetValue = literalTools.parseInt(offsetText);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
offset_or_label_absolute[int baseAddress] returns[int address]
|
||||||
|
: offset {$address = $offset.offsetValue + $baseAddress;}
|
||||||
|
| label_ref {$address = $label_ref.labelAddress;};
|
||||||
|
|
||||||
offset_or_label returns[int offsetValue]
|
offset_or_label returns[int offsetValue]
|
||||||
: offset {$offsetValue = $offset.offsetValue;}
|
: offset {$offsetValue = $offset.offsetValue;}
|
||||||
| label_ref
|
| label_ref {$offsetValue = $label_ref.labelAddress-$method::currentAddress;};
|
||||||
{
|
|
||||||
int labelAddress = $label_ref.labelAddress;
|
|
||||||
int currentAddress = $method::currentAddress;
|
|
||||||
|
|
||||||
$offsetValue = labelAddress-currentAddress;
|
|
||||||
};
|
|
||||||
|
|
||||||
instruction returns[Instruction instruction]
|
instruction returns[Instruction instruction]
|
||||||
: //e.g. goto endloop:
|
: //e.g. goto endloop:
|
||||||
|
@ -47,7 +47,7 @@ public abstract class ItemReference<T extends Item<T>, S extends ItemReference<T
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setReference(T item) {
|
public void setReference(T item) {
|
||||||
this.item = item;
|
this.item = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,15 +33,28 @@ import org.JesusFreke.dexlib.*;
|
|||||||
public class StartLocal extends CompositeField<StartLocal> implements DebugInstruction<StartLocal> {
|
public class StartLocal extends CompositeField<StartLocal> implements DebugInstruction<StartLocal> {
|
||||||
private final Field[] fields;
|
private final Field[] fields;
|
||||||
|
|
||||||
|
private final ByteField opcodeField;
|
||||||
|
private final SignedLeb128Field registerNumber;
|
||||||
|
private final IndexedItemReference<StringIdItem> localName;
|
||||||
|
private final IndexedItemReference<TypeIdItem> localType;
|
||||||
|
|
||||||
public StartLocal(DexFile dexFile) {
|
public StartLocal(DexFile dexFile) {
|
||||||
fields = new Field[] {
|
fields = new Field[] {
|
||||||
new ByteField((byte)0x03),
|
opcodeField = new ByteField((byte)0x03),
|
||||||
new SignedLeb128Field(),
|
registerNumber = new SignedLeb128Field(),
|
||||||
new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new Leb128p1Field()),
|
localName = new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new Leb128p1Field()),
|
||||||
new IndexedItemReference<TypeIdItem>(dexFile.TypeIdsSection, new Leb128p1Field()),
|
localType = new IndexedItemReference<TypeIdItem>(dexFile.TypeIdsSection, new Leb128p1Field()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public StartLocal(DexFile dexFile, int registerNumber, StringIdItem localName, TypeIdItem localType) {
|
||||||
|
this(dexFile);
|
||||||
|
this.registerNumber.cacheValue(registerNumber);
|
||||||
|
this.localName.setReference(localName);
|
||||||
|
this.localType.setReference(localType);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
protected Field[] getFields() {
|
protected Field[] getFields() {
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ import org.JesusFreke.dexlib.debug.*;
|
|||||||
import org.JesusFreke.dexlib.DexFile;
|
import org.JesusFreke.dexlib.DexFile;
|
||||||
import org.JesusFreke.dexlib.DebugInfoItem;
|
import org.JesusFreke.dexlib.DebugInfoItem;
|
||||||
import org.JesusFreke.dexlib.StringIdItem;
|
import org.JesusFreke.dexlib.StringIdItem;
|
||||||
|
import org.JesusFreke.dexlib.TypeIdItem;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -64,12 +65,22 @@ public class DebugInfoBuilder
|
|||||||
public DebugInfoBuilder() {
|
public DebugInfoBuilder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addLine(int address, int line) {
|
private void checkAddress(int address) {
|
||||||
hasData = true;
|
|
||||||
|
|
||||||
if (lastAddress > address) {
|
if (lastAddress > address) {
|
||||||
throw new RuntimeException("Cannot add an event with an address before the address of the prior event");
|
throw new RuntimeException("Cannot add an event with an address before the address of the prior event");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addParameterName(String parameterName) {
|
||||||
|
hasData = true;
|
||||||
|
|
||||||
|
parameterNames.add(parameterName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addLine(int address, int line) {
|
||||||
|
hasData = true;
|
||||||
|
|
||||||
|
checkAddress(address);
|
||||||
|
|
||||||
if (lineStart == 0) {
|
if (lineStart == 0) {
|
||||||
lineStart = line;
|
lineStart = line;
|
||||||
@ -78,10 +89,12 @@ public class DebugInfoBuilder
|
|||||||
events.add(new LineEvent(address, line));
|
events.add(new LineEvent(address, line));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addParameterName(String parameterName) {
|
public void addLocal(int address, int registerNumber, String localName, String localType) {
|
||||||
hasData = true;
|
hasData = true;
|
||||||
|
|
||||||
parameterNames.add(parameterName);
|
checkAddress(address);
|
||||||
|
|
||||||
|
events.add(new StartLocalEvent(address, registerNumber, localName, localType));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getParameterNameCount() {
|
public int getParameterNameCount() {
|
||||||
@ -103,7 +116,7 @@ public class DebugInfoBuilder
|
|||||||
currentLine = lineStart;
|
currentLine = lineStart;
|
||||||
|
|
||||||
for (Event event: events) {
|
for (Event event: events) {
|
||||||
event.emit(debugInstructions);
|
event.emit(dexFile, debugInstructions);
|
||||||
}
|
}
|
||||||
debugInstructions.add(new EndSequence());
|
debugInstructions.add(new EndSequence());
|
||||||
|
|
||||||
@ -121,7 +134,7 @@ public class DebugInfoBuilder
|
|||||||
private interface Event
|
private interface Event
|
||||||
{
|
{
|
||||||
int getAddress();
|
int getAddress();
|
||||||
void emit(List<DebugInstruction> debugInstructions);
|
void emit(DexFile dexFile, List<DebugInstruction> debugInstructions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LineEvent implements Event
|
private class LineEvent implements Event
|
||||||
@ -138,7 +151,7 @@ public class DebugInfoBuilder
|
|||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void emit(List<DebugInstruction> debugInstructions) {
|
public void emit(DexFile dexFile, List<DebugInstruction> debugInstructions) {
|
||||||
int lineDelta = line - currentLine;
|
int lineDelta = line - currentLine;
|
||||||
int addressDelta = address - currentAddress;
|
int addressDelta = address - currentAddress;
|
||||||
|
|
||||||
@ -162,4 +175,37 @@ public class DebugInfoBuilder
|
|||||||
return (byte)(FIRST_SPECIAL + (addressDelta * LINE_RANGE) + (lineDelta - LINE_BASE));
|
return (byte)(FIRST_SPECIAL + (addressDelta * LINE_RANGE) + (lineDelta - LINE_BASE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class StartLocalEvent implements Event
|
||||||
|
{
|
||||||
|
private final int address;
|
||||||
|
private final int registerNum;
|
||||||
|
private final String localName;
|
||||||
|
private final String localType;
|
||||||
|
|
||||||
|
public StartLocalEvent(int address, int registerNum, String localName, String localType) {
|
||||||
|
this.address = address;
|
||||||
|
this.registerNum = registerNum;
|
||||||
|
this.localName = localName;
|
||||||
|
this.localType = localType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAddress()
|
||||||
|
{
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void emit(DexFile dexFile, List<DebugInstruction> debugInstructions)
|
||||||
|
{
|
||||||
|
int addressDelta = address-currentAddress;
|
||||||
|
|
||||||
|
if (addressDelta > 0) {
|
||||||
|
debugInstructions.add(new AdvancePC(addressDelta));
|
||||||
|
currentAddress = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
debugInstructions.add(new StartLocal(dexFile, registerNum, new StringIdItem(dexFile, localName),
|
||||||
|
new TypeIdItem(dexFile, localType)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -374,8 +374,15 @@ SparseSwitch:
|
|||||||
.line 4
|
.line 4
|
||||||
|
|
||||||
;0
|
;0
|
||||||
|
|
||||||
|
|
||||||
const-string v0, "This shouldn't be displayed!"
|
const-string v0, "This shouldn't be displayed!"
|
||||||
|
|
||||||
|
.local v0, testVarName Ljava/lang/String;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;2
|
;2
|
||||||
|
|
||||||
tryStart:
|
tryStart:
|
||||||
@ -405,7 +412,8 @@ SparseSwitch:
|
|||||||
|
|
||||||
;11
|
;11
|
||||||
|
|
||||||
.catch Ljava/lang/Exception; from tryStart: to tryEnd: using handler:
|
|
||||||
|
.catch Ljava/lang/Exception; {tryStart: .. tryEnd:} handler:
|
||||||
|
|
||||||
handler:
|
handler:
|
||||||
const-string v0, "In the exception handler."
|
const-string v0, "In the exception handler."
|
||||||
|
Loading…
x
Reference in New Issue
Block a user