diff --git a/smali/src/main/antlr3/smaliParser.g b/smali/src/main/antlr3/smaliParser.g index 1ec8a2ac..23f6bed8 100644 --- a/smali/src/main/antlr3/smaliParser.g +++ b/smali/src/main/antlr3/smaliParser.g @@ -658,6 +658,9 @@ literal | type_field_method_literal | enum_literal; +parsed_integer_literal returns[int value] + : integer_literal { $value = LiteralTools.parseInt($integer_literal.text); }; + integral_literal : LONG_LITERAL | integer_literal @@ -1116,12 +1119,19 @@ insn_format51l returns [int size] -> ^(I_STATEMENT_FORMAT51l[$start, "I_STATEMENT_FORMAT51l"] INSTRUCTION_FORMAT51l REGISTER fixed_literal); insn_array_data_directive returns [int size] - : ARRAY_DATA_DIRECTIVE + : ARRAY_DATA_DIRECTIVE + parsed_integer_literal + { + int elementWidth = $parsed_integer_literal.value; + if (elementWidth != 4 && elementWidth != 8 && elementWidth != 1 && elementWidth != 2) { + throw new SemanticException(input, $start, "Invalid element width: \%d. Must be 1, 2, 4 or 8", elementWidth); + } + } - integral_literal (fixed_literal {$size+=$fixed_literal.size;})* END_ARRAY_DATA_DIRECTIVE - {$size = (($size + 1)/2)*2 + 8;} + (fixed_literal {$size+=elementWidth;})* END_ARRAY_DATA_DIRECTIVE + {$size = (($size + 1) & ~1) + 8;} - -> ^(I_STATEMENT_ARRAY_DATA[$start, "I_STATEMENT_ARRAY_DATA"] ^(I_ARRAY_ELEMENT_SIZE integral_literal) + -> ^(I_STATEMENT_ARRAY_DATA[$start, "I_STATEMENT_ARRAY_DATA"] ^(I_ARRAY_ELEMENT_SIZE parsed_integer_literal) ^(I_ARRAY_ELEMENTS fixed_literal*)); insn_packed_switch_directive returns [int size] diff --git a/smali/src/main/antlr3/smaliTreeWalker.g b/smali/src/main/antlr3/smaliTreeWalker.g index d530e558..30c52d62 100644 --- a/smali/src/main/antlr3/smaliTreeWalker.g +++ b/smali/src/main/antlr3/smaliTreeWalker.g @@ -269,19 +269,17 @@ literal returns[EncodedValue encodedValue] | method_literal { $encodedValue = new ImmutableMethodEncodedValue($method_literal.value); } | enum_literal { $encodedValue = new ImmutableEnumEncodedValue($enum_literal.value); }; - //everything but string -fixed_size_literal returns[byte[\] value] - : integer_literal { $value = LiteralTools.intToBytes($integer_literal.value); } - | long_literal { $value = LiteralTools.longToBytes($long_literal.value); } - | short_literal { $value = LiteralTools.shortToBytes($short_literal.value); } - | byte_literal { $value = new byte[] { $byte_literal.value }; } - | float_literal { $value = LiteralTools.floatToBytes($float_literal.value); } - | double_literal { $value = LiteralTools.doubleToBytes($double_literal.value); } - | char_literal { $value = LiteralTools.charToBytes($char_literal.value); } - | bool_literal { $value = LiteralTools.boolToBytes($bool_literal.value); }; +fixed_64bit_literal_number returns[Number value] + : integer_literal { $value = $integer_literal.value; } + | long_literal { $value = $long_literal.value; } + | short_literal { $value = $short_literal.value; } + | byte_literal { $value = $byte_literal.value; } + | float_literal { $value = Float.floatToRawIntBits($float_literal.value); } + | double_literal { $value = Double.doubleToRawLongBits($double_literal.value); } + | char_literal { $value = (int)$char_literal.value; } + | bool_literal { $value = $bool_literal.value?1:0; }; -//everything but string fixed_64bit_literal returns[long value] : integer_literal { $value = $integer_literal.value; } | long_literal { $value = $long_literal.value; } @@ -303,12 +301,12 @@ fixed_32bit_literal returns[int value] | char_literal { $value = $char_literal.value; } | bool_literal { $value = $bool_literal.value?1:0; }; -array_elements returns[List elements] +array_elements returns[List elements] : {$elements = Lists.newArrayList();} ^(I_ARRAY_ELEMENTS - (fixed_size_literal + (fixed_64bit_literal_number { - $elements.add($fixed_size_literal.value); + $elements.add($fixed_64bit_literal_number.value); })*); packed_switch_elements[int baseAddress, int firstKey] returns[List elements] @@ -1248,25 +1246,10 @@ insn_array_data_directive[List instructions] returns[int outRegiste : //e.g. .array-data 4 1000000 .end array-data ^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE short_integral_literal) array_elements) { - // TODO: reimplement, after changing how it's parsed - /* int elementWidth = $short_integral_literal.value; - List byteValues = $array_elements.elements; + List elements = $array_elements.elements; - int length = 0; - for (byte[] byteValue: byteValues) { - length+=byteValue.length; - } - - byte[] encodedValues = new byte[length]; - int index = 0; - for (byte[] byteValue: byteValues) { - System.arraycopy(byteValue, 0, encodedValues, index, byteValue.length); - index+=byteValue.length; - } - - $instructions.add(new ImmutableArrayPayload(elementWidth, null)); - */ + $instructions.add(new ImmutableArrayPayload(elementWidth, $array_elements.elements)); }; insn_packed_switch_directive[List instructions] returns[int outRegisters]