Added support for specifying a numeric offset instead of a label for the target of goto

git-svn-id: https://smali.googlecode.com/svn/trunk@14 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
JesusFreke@JesusFreke.com 2009-04-26 07:40:09 +00:00
parent 2b66dd2363
commit 32a79f0f28
4 changed files with 50 additions and 12 deletions

View File

@ -232,7 +232,7 @@ REGISTERS_PHRASE
INSTRUCTION_FORMAT10t_PHRASE
: INSTRUCTION_FORMAT10t_EMIT
WS
LABEL_EMIT;
(LABEL_EMIT | OFFSET_EMIT);
INSTRUCTION_FORMAT10x_PHRASE
: INSTRUCTION_FORMAT10x_EMIT;
@ -306,6 +306,12 @@ INSTRUCTION_FORMAT3rc_METHOD_PHRASE
FULLY_QUALIFIED_MEMBER_NAME_EMITCHILDREN
METHOD_PROTOTYPE_EMITCHILDREN;
fragment OFFSET_EMIT
: OFFSET {emit($OFFSET, OFFSET);};
fragment OFFSET
: ('+' | '-') INTEGER_LITERAL;
fragment LABEL_EMIT
: LABEL {emit($LABEL, LABEL);};
LABEL

View File

@ -130,8 +130,9 @@ label
instruction returns [int size]
: //e.g. goto endloop:
INSTRUCTION_FORMAT10t LABEL {$size = Format10t.Format.getByteCount();}
-> ^(I_STATEMENT_FORMAT10t[$start, "I_STATEMENT_FORMAT10t"] INSTRUCTION_FORMAT10t LABEL)
//e.g. goto +3
INSTRUCTION_FORMAT10t (LABEL | OFFSET){$size = Format10t.Format.getByteCount();}
-> ^(I_STATEMENT_FORMAT10t[$start, "I_STATEMENT_FORMAT10t"] INSTRUCTION_FORMAT10t LABEL? OFFSET?)
| //e.g. return
INSTRUCTION_FORMAT10x {$size = Format10x.Format.getByteCount();}
-> ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x)

View File

@ -306,21 +306,37 @@ label returns[String labelName]
return label.substring(0, label.length()-1);
};
instruction returns[Instruction instruction]
: //e.g. goto endloop:
^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t label_ref)
offset returns[int offsetValue]
: OFFSET
{
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10t.text);
String offsetText = $OFFSET.text;
if (offsetText.startsWith("+")) {
offsetText = offsetText.substring(1);
}
$offsetValue = Integer.parseInt(offsetText);
};
offset_or_label returns[int offsetValue]
: offset {$offsetValue = $offset.offsetValue;}
| label_ref
{
int labelAddress = $label_ref.labelAddress;
int currentAddress = $method::currentAddress;
int addressOffset = labelAddress - currentAddress;
$offsetValue = labelAddress-currentAddress;
};
instruction returns[Instruction instruction]
: //e.g. goto endloop:
^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t offset_or_label)
{
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10t.text);
int addressOffset = $offset_or_label.offsetValue;
if (addressOffset < Byte.MIN_VALUE || addressOffset > Byte.MAX_VALUE) {
//TODO: throw correct exception type
throw new RuntimeException("The offset to the given label is out of range. The offset is " + Integer.toString(addressOffset) + ". The range for this opcode is [-128, 127].");
throw new RuntimeException("The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-128, 127].");
}
$instruction = Format10t.Format.make(dexFile, opcode.value, (byte)addressOffset);

View File

@ -19,6 +19,7 @@
;-8
;7
;But this should!
;But this should!
.method static constructor <clinit>()V ;test
@ -145,6 +146,7 @@
;test format10t with a label
goto SKIP:
const-string v1, "This shouldn't be displayed!"
@ -159,6 +161,19 @@
move-result-object v2
;test format10t with an offset
goto +3
const-string v1, "This shouldn't be displayed!"
const-string v1,"But this should!"
invoke-virtual {v2, v1}, java/lang/String/concat(Ljava/lang/String;)Ljava/lang/String;
move-result-object v2
invoke-virtual {v2, v3}, java/lang/String/concat(Ljava/lang/String;)Ljava/lang/String;
move-result-object v2
check-cast v4, Landroid/app/Activity;