- add support for the .end local directive

- add support for the .restart local directive
- add support for the .prologue directive
- add support for the .epilogue directive
- add support for the "extended" .local directive (i.e. the optional signature)
- add support for the .source directive

git-svn-id: https://smali.googlecode.com/svn/trunk@47 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
JesusFreke@JesusFreke.com 2009-05-23 07:57:13 +00:00
parent f175e1d987
commit 0d16dfbfcc
10 changed files with 374 additions and 33 deletions

View File

@ -480,8 +480,25 @@ LOCAL_PHRASE
WS? ',' WS?
SIMPLE_NAME_EMIT
WS
FIELD_TYPE_DESCRIPTOR_EMITCHILD;
FIELD_TYPE_DESCRIPTOR_EMITCHILD
WS?
( ',' WS? STRING_LITERAL_EMIT)?;
END_LOCAL_PHRASE
: END_LOCAL_DIRECTIVE_EMIT
WS
REGISTER_EMIT;
RESTART_LOCAL_PHRASE
: RESTART_LOCAL_DIRECTIVE_EMIT
WS
REGISTER_EMIT;
PROLOGUE_PHRASE
: PROLOGUE_DIRECTIVE_EMIT;
EPILOGUE_PHRASE
: EPILOGUE_DIRECTIVE_EMIT;
//TODO: add support for both relative and absolute offsets?
fragment OFFSET_EMIT
@ -583,6 +600,26 @@ fragment LOCAL_DIRECTIVE_EMIT
: LOCAL_DIRECTIVE {emit($LOCAL_DIRECTIVE, LOCAL_DIRECTIVE);};
fragment LOCAL_DIRECTIVE
: '.local';
fragment END_LOCAL_DIRECTIVE_EMIT
: END_LOCAL_DIRECTIVE {emit($END_LOCAL_DIRECTIVE, END_LOCAL_DIRECTIVE);};
fragment END_LOCAL_DIRECTIVE
: '.end local';
fragment RESTART_LOCAL_DIRECTIVE_EMIT
: RESTART_LOCAL_DIRECTIVE {emit($RESTART_LOCAL_DIRECTIVE, RESTART_LOCAL_DIRECTIVE);};
fragment RESTART_LOCAL_DIRECTIVE
: '.restart local';
fragment PROLOGUE_DIRECTIVE_EMIT
: PROLOGUE_DIRECTIVE {emit($PROLOGUE_DIRECTIVE, PROLOGUE_DIRECTIVE);};
fragment PROLOGUE_DIRECTIVE
: '.prologue';
fragment EPILOGUE_DIRECTIVE_EMIT
: EPILOGUE_DIRECTIVE {emit($EPILOGUE_DIRECTIVE, EPILOGUE_DIRECTIVE);};
fragment EPILOGUE_DIRECTIVE
: '.epilogue';
fragment REGISTER_EMIT
: REGISTER {emit($REGISTER, REGISTER);};

View File

@ -71,6 +71,10 @@ tokens {
I_ORDERED_DEBUG_DIRECTIVES;
I_LINE;
I_LOCAL;
I_END_LOCAL;
I_RESTART_LOCAL;
I_PROLOGUE;
I_EPILOGUE;
I_STATEMENTS;
I_STATEMENT_FORMAT10t;
I_STATEMENT_FORMAT10x;
@ -252,14 +256,40 @@ parameter_directive
ordered_debug_directive
: line_directive
| local_directive;
| local_directive
| end_local_directive
| restart_local_directive
| prologue_directive
| epilogue_directive
| source_directive;
line_directive
: LINE_DIRECTIVE integral_literal -> ^(I_LINE integral_literal I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
: 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)]);
: LOCAL_DIRECTIVE REGISTER SIMPLE_NAME field_type_descriptor STRING_LITERAL?
-> ^(I_LOCAL[$start, "I_LOCAL"] REGISTER SIMPLE_NAME field_type_descriptor STRING_LITERAL? I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
end_local_directive
: END_LOCAL_DIRECTIVE REGISTER
-> ^(I_END_LOCAL[$start, "I_END_LOCAL"] REGISTER I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
restart_local_directive
: RESTART_LOCAL_DIRECTIVE REGISTER
-> ^(I_RESTART_LOCAL[$start, "I_RESTART_LOCAL"] REGISTER I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
prologue_directive
: PROLOGUE_DIRECTIVE
-> ^(I_PROLOGUE[$start, "I_PROLOGUE"] I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
epilogue_directive
: EPILOGUE_DIRECTIVE
-> ^(I_EPILOGUE[$start, "I_EPILOGUE"] I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
source_directive
: SOURCE_DIRECTIVE STRING_LITERAL
-> ^(I_SOURCE[$start, "I_SOURCE"] STRING_LITERAL I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
label
: LABEL -> ^(I_LABEL LABEL I_ADDRESS[$start, Integer.toString($method::currentAddress)]);

View File

@ -446,7 +446,14 @@ parameter
));
ordered_debug_directives
: ^(I_ORDERED_DEBUG_DIRECTIVES (line | local)*);
: ^(I_ORDERED_DEBUG_DIRECTIVES ( line
| local
| end_local
| restart_local
| prologue
| epilogue
| source
)*);
line
: ^(I_LINE integral_literal address)
@ -454,15 +461,51 @@ line
$method::debugInfo.addLine($address.address, $integral_literal.value);
};
local : ^(I_LOCAL REGISTER SIMPLE_NAME field_type_descriptor address)
local
: ^(I_LOCAL REGISTER SIMPLE_NAME field_type_descriptor string_literal? address)
{
int registerNumber = parseRegister_short($REGISTER.text);
$method::debugInfo.addLocal($address.address, registerNumber, $SIMPLE_NAME.text, $field_type_descriptor.type.toString());
if ($string_literal.value != null) {
$method::debugInfo.addLocalExtended($address.address, registerNumber, $SIMPLE_NAME.text, $field_type_descriptor.type.toString(), $string_literal.value);
} else {
$method::debugInfo.addLocal($address.address, registerNumber, $SIMPLE_NAME.text, $field_type_descriptor.type.toString());
}
};
end_local
: ^(I_END_LOCAL REGISTER address)
{
int registerNumber = parseRegister_short($REGISTER.text);
$method::debugInfo.addEndLocal($address.address, registerNumber);
};
restart_local
: ^(I_RESTART_LOCAL REGISTER address)
{
int registerNumber = parseRegister_short($REGISTER.text);
$method::debugInfo.addRestartLocal($address.address, registerNumber);
};
prologue
: ^(I_PROLOGUE address)
{
$method::debugInfo.addPrologue($address.address);
};
epilogue
: ^(I_EPILOGUE address)
{
$method::debugInfo.addEpilogue($address.address);
};
source
: ^(I_SOURCE string_literal address)
{
$method::debugInfo.addSetFile($address.address, $string_literal.value);
};
statements returns[ArrayList<Instruction> instructions]
@init

View File

@ -33,13 +33,21 @@ import org.JesusFreke.dexlib.*;
public class EndLocal extends CompositeField<EndLocal> implements DebugInstruction<EndLocal> {
private final Field[] fields;
private final ByteField opcode;
private final Leb128Field registerNumber;
public EndLocal() {
fields = new Field[] {
new ByteField((byte)0x05),
new Leb128Field()
opcode = new ByteField((byte)0x05),
registerNumber = new Leb128Field()
};
}
public EndLocal(int registerNumber) {
this();
this.registerNumber.cacheValue(registerNumber);
}
protected Field[] getFields() {
return fields;
}

View File

@ -33,13 +33,21 @@ import org.JesusFreke.dexlib.*;
public class RestartLocal extends CompositeField<RestartLocal> implements DebugInstruction<RestartLocal> {
private final Field[] fields;
private final ByteField opcode;
private final Leb128Field registerNumber;
public RestartLocal() {
fields = new Field[] {
new ByteField((byte)0x06),
new SignedLeb128Field()
opcode = new ByteField((byte)0x06),
registerNumber = new Leb128Field()
};
}
public RestartLocal(int registerNumber) {
this();
this.registerNumber.cacheValue(registerNumber);
}
protected Field[] getFields() {
return fields;
}

View File

@ -33,13 +33,21 @@ import org.JesusFreke.dexlib.*;
public class SetFile extends CompositeField<SetFile> implements DebugInstruction<SetFile> {
private final Field[] fields;
private final ByteField opcode;
private final IndexedItemReference<StringIdItem> fileName;
public SetFile(DexFile dexFile) {
fields = new Field[] {
new ByteField((byte)0x09),
new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new Leb128p1Field())
opcode = new ByteField((byte)0x09),
fileName = new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new Leb128p1Field())
};
}
public SetFile(DexFile dexFile, StringIdItem fileName) {
this(dexFile);
this.fileName.setReference(fileName);
}
protected Field[] getFields() {
return fields;
}

View File

@ -51,8 +51,7 @@ public class StartLocal extends CompositeField<StartLocal> implements DebugInstr
this(dexFile);
this.registerNumber.cacheValue(registerNumber);
this.localName.setReference(localName);
this.localType.setReference(localType);
this.localType.setReference(localType);
}
protected Field[] getFields() {

View File

@ -33,16 +33,32 @@ import org.JesusFreke.dexlib.*;
public class StartLocalExtended extends CompositeField<StartLocalExtended> implements DebugInstruction<StartLocalExtended> {
private final Field[] fields;
private final ByteField opcodeField;
//TODO: signed or unsigned leb?
private final SignedLeb128Field registerNumber;
private final IndexedItemReference<StringIdItem> localName;
private final IndexedItemReference<TypeIdItem> localType;
private final IndexedItemReference<StringIdItem> signature;
public StartLocalExtended(DexFile dexFile) {
fields = new Field[] {
new ByteField((byte)0x04),
new SignedLeb128Field(),
new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new Leb128p1Field()),
new IndexedItemReference<TypeIdItem>(dexFile.TypeIdsSection, new Leb128p1Field()),
new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new Leb128p1Field())
opcodeField = new ByteField((byte)0x04),
registerNumber = new SignedLeb128Field(),
localName = new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new Leb128p1Field()),
localType = new IndexedItemReference<TypeIdItem>(dexFile.TypeIdsSection, new Leb128p1Field()),
signature = new IndexedItemReference<StringIdItem>(dexFile.StringIdsSection, new Leb128p1Field())
};
}
public StartLocalExtended(DexFile dexFile, int registerNumber, StringIdItem localName, TypeIdItem localType,
StringIdItem signature) {
this(dexFile);
this.registerNumber.cacheValue(registerNumber);
this.localName.setReference(localName);
this.localType.setReference(localType);
this.signature.setReference(signature);
}
protected Field[] getFields() {
return fields;
}

View File

@ -97,6 +97,55 @@ public class DebugInfoBuilder
events.add(new StartLocalEvent(address, registerNumber, localName, localType));
}
public void addLocalExtended(int address, int registerNumber, String localName, String localType,
String signature) {
hasData = true;
checkAddress(address);
events.add(new StartLocalExtendedEvent(address, registerNumber, localName, localType, signature));
}
public void addEndLocal(int address, int registerNumber) {
hasData = true;
checkAddress(address);
events.add(new EndLocalEvent(address, registerNumber));
}
public void addRestartLocal(int address, int registerNumber) {
hasData = true;
checkAddress(address);
events.add(new RestartLocalEvent(address, registerNumber));
}
public void addPrologue(int address) {
hasData = true;
checkAddress(address);
events.add(new PrologueEvent(address));
}
public void addEpilogue(int address) {
hasData = true;
checkAddress(address);
events.add(new EpilogueEvent(address));
}
public void addSetFile(int address, String fileName) {
hasData = true;
checkAddress(address);
events.add(new SetFileEvent(address, fileName));
}
public int getParameterNameCount() {
return parameterNames.size();
}
@ -137,6 +186,15 @@ public class DebugInfoBuilder
void emit(DexFile dexFile, List<DebugInstruction> debugInstructions);
}
private void emitAdvancePC(int address, List<DebugInstruction> debugInstructions) {
int addressDelta = address-currentAddress;
if (addressDelta > 0) {
debugInstructions.add(new AdvancePC(addressDelta));
currentAddress = address;
}
}
private class LineEvent implements Event
{
private final int address;
@ -190,22 +248,145 @@ public class DebugInfoBuilder
this.localType = localType;
}
public int getAddress()
{
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;
}
public void emit(DexFile dexFile, List<DebugInstruction> debugInstructions) {
emitAdvancePC(address, debugInstructions);
debugInstructions.add(new StartLocal(dexFile, registerNum, new StringIdItem(dexFile, localName),
new TypeIdItem(dexFile, localType)));
}
}
private class StartLocalExtendedEvent implements Event
{
private final int address;
private final int registerNum;
private final String localName;
private final String localType;
private final String signature;
public StartLocalExtendedEvent(int address, int registerNum, String localName, String localType,
String signature) {
this.address = address;
this.registerNum = registerNum;
this.localName = localName;
this.localType = localType;
this.signature = signature;
}
public int getAddress() {
return address;
}
public void emit(DexFile dexFile, List<DebugInstruction> debugInstructions) {
emitAdvancePC(address, debugInstructions);
debugInstructions.add(new StartLocalExtended(dexFile, registerNum, new StringIdItem(dexFile, localName),
new TypeIdItem(dexFile, localType), new StringIdItem(dexFile, signature)));
}
}
private class EndLocalEvent implements Event
{
private final int address;
private final int registerNum;
public EndLocalEvent(int address, int registerNum) {
this.address = address;
this.registerNum = registerNum;
}
public int getAddress() {
return address;
}
public void emit(DexFile dexFile, List<DebugInstruction> debugInstructions) {
emitAdvancePC(address, debugInstructions);
debugInstructions.add(new EndLocal(registerNum));
}
}
private class RestartLocalEvent implements Event
{
private final int address;
private final int registerNum;
public RestartLocalEvent(int address, int registerNum) {
this.address = address;
this.registerNum = registerNum;
}
public int getAddress() {
return address;
}
public void emit(DexFile dexFile, List<DebugInstruction> debugInstructions) {
emitAdvancePC(address, debugInstructions);
debugInstructions.add(new RestartLocal(registerNum));
}
}
private class PrologueEvent implements Event
{
private final int address;
public PrologueEvent(int address) {
this.address = address;
}
public int getAddress() {
return address;
}
public void emit(DexFile dexFile, List<DebugInstruction> debugInstructions) {
emitAdvancePC(address, debugInstructions);
debugInstructions.add(new SetPrologueEnd());
}
}
private class EpilogueEvent implements Event
{
private final int address;
public EpilogueEvent(int address) {
this.address = address;
}
public int getAddress() {
return address;
}
public void emit(DexFile dexFile, List<DebugInstruction> debugInstructions) {
emitAdvancePC(address, debugInstructions);
debugInstructions.add(new SetEpilogueBegin());
}
}
private class SetFileEvent implements Event
{
private final int address;
private final String fileName;
public SetFileEvent(int address, String fileName) {
this.address = address;
this.fileName = fileName;
}
public int getAddress() {
return address;
}
public void emit(DexFile dexFile, List<DebugInstruction> debugInstructions) {
emitAdvancePC(address, debugInstructions);
debugInstructions.add(new SetFile(dexFile, new StringIdItem(dexFile, fileName)));
}
}
}

View File

@ -380,6 +380,8 @@ SparseSwitch:
.local v0, testVarName Ljava/lang/String;
.prologue
@ -388,10 +390,14 @@ SparseSwitch:
tryStart:
new-instance v1, Ljava/lang/Exception;
.local v1, testVarName2 Ljava/lang/String;, "some weird type"
.line 2
;4
.end local v0
invoke-direct {v1}, java/lang/Exception/<init>()V
;7
@ -401,6 +407,8 @@ SparseSwitch:
nop
nop
.restart local v0
.line 5
;10
@ -408,11 +416,14 @@ SparseSwitch:
return-object v0
.source "blahblah.java"
.line 90
;11
.epilogue
.catch Ljava/lang/Exception; {tryStart: .. tryEnd:} handler:
handler: