mirror of
https://github.com/revanced/smali.git
synced 2025-05-11 20:04:28 +02:00
- 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:
parent
f175e1d987
commit
0d16dfbfcc
@ -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);};
|
||||
|
@ -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)]);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user