mirror of
https://github.com/revanced/smali.git
synced 2025-05-19 15:37:06 +02:00
Change .param and .local syntax, to be able to handle empty name/type/signature
This commit is contained in:
parent
aa860984c0
commit
3e4e5ec7a4
@ -54,19 +54,12 @@ public class EndLocalMethodItem extends DebugMethodItem {
|
|||||||
writer.write(".end local ");
|
writer.write(".end local ");
|
||||||
registerFormatter.writeTo(writer, endLocal.getRegister());
|
registerFormatter.writeTo(writer, endLocal.getRegister());
|
||||||
|
|
||||||
//TODO: what if name is null, but there is a type?
|
|
||||||
String name = endLocal.getName();
|
String name = endLocal.getName();
|
||||||
if (name != null) {
|
String type = endLocal.getType();
|
||||||
|
String signature = endLocal.getSignature();
|
||||||
|
if (name != null || type != null || signature != null) {
|
||||||
writer.write(" # ");
|
writer.write(" # ");
|
||||||
writer.write(name);
|
LocalFormatter.writeLocal(writer, name, type, signature);
|
||||||
writer.write(':');
|
|
||||||
writer.write(endLocal.getType());
|
|
||||||
String signature = endLocal.getSignature();
|
|
||||||
if (signature != null) {
|
|
||||||
writer.write(",\"");
|
|
||||||
writer.write(signature);
|
|
||||||
writer.write('"');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Google Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following disclaimer
|
||||||
|
* in the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Google Inc. nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jf.baksmali.Adaptors.Debug;
|
||||||
|
|
||||||
|
import org.jf.baksmali.Adaptors.ReferenceFormatter;
|
||||||
|
import org.jf.util.IndentingWriter;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class LocalFormatter {
|
||||||
|
/**
|
||||||
|
* Writes out the given local info
|
||||||
|
*
|
||||||
|
* The written string will be something like:
|
||||||
|
*
|
||||||
|
* "localVar":Ljava/lang/String;, "SomeSignature"
|
||||||
|
* "localVar":Ljava/lang/String;
|
||||||
|
* "localVar":V, "SomeSignature"
|
||||||
|
* null:Ljava/lang/String;, "SomeSignature"
|
||||||
|
* null:V, "SomeSignature"
|
||||||
|
*
|
||||||
|
* One of name, type or signature must be non-null
|
||||||
|
*/
|
||||||
|
public static void writeLocal(@Nonnull IndentingWriter writer, @Nullable String name, @Nullable String type,
|
||||||
|
@Nullable String signature) throws IOException {
|
||||||
|
if (name != null) {
|
||||||
|
ReferenceFormatter.writeStringReference(writer, name);
|
||||||
|
} else {
|
||||||
|
writer.write("null");
|
||||||
|
}
|
||||||
|
writer.write(':');
|
||||||
|
if (type != null) {
|
||||||
|
writer.write(type);
|
||||||
|
} else {
|
||||||
|
writer.write("V");
|
||||||
|
}
|
||||||
|
if (signature != null) {
|
||||||
|
writer.write(", ");
|
||||||
|
ReferenceFormatter.writeStringReference(writer, signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -54,19 +54,12 @@ public class RestartLocalMethodItem extends DebugMethodItem {
|
|||||||
writer.write(".restart local ");
|
writer.write(".restart local ");
|
||||||
registerFormatter.writeTo(writer, restartLocal.getRegister());
|
registerFormatter.writeTo(writer, restartLocal.getRegister());
|
||||||
|
|
||||||
//TODO: what if name is null, but there is a type?
|
|
||||||
String name = restartLocal.getName();
|
String name = restartLocal.getName();
|
||||||
if (name != null) {
|
String type = restartLocal.getType();
|
||||||
|
String signature = restartLocal.getSignature();
|
||||||
|
if (name != null || type != null || signature != null) {
|
||||||
writer.write(" # ");
|
writer.write(" # ");
|
||||||
writer.write(name);
|
LocalFormatter.writeLocal(writer, name, type, signature);
|
||||||
writer.write(':');
|
|
||||||
writer.write(restartLocal.getType());
|
|
||||||
String signature = restartLocal.getSignature();
|
|
||||||
if (signature != null) {
|
|
||||||
writer.write(",\"");
|
|
||||||
writer.write(signature);
|
|
||||||
writer.write('"');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -53,17 +53,14 @@ public class StartLocalMethodItem extends DebugMethodItem {
|
|||||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||||
writer.write(".local ");
|
writer.write(".local ");
|
||||||
registerFormatter.writeTo(writer, startLocal.getRegister());
|
registerFormatter.writeTo(writer, startLocal.getRegister());
|
||||||
writer.write(", ");
|
|
||||||
//TODO: what about when name or type is null? Can the name contain a colon?
|
String name = startLocal.getName();
|
||||||
writer.write(startLocal.getName());
|
String type = startLocal.getType();
|
||||||
writer.write(':');
|
|
||||||
writer.write(startLocal.getType());
|
|
||||||
String signature = startLocal.getSignature();
|
String signature = startLocal.getSignature();
|
||||||
if (signature != null) {
|
|
||||||
writer.write(",\"");
|
if (name != null || type != null || signature != null) {
|
||||||
//TODO: does dalvik require this be in any format? Does it need to be escaped?
|
writer.write(", ");
|
||||||
writer.write(signature);
|
LocalFormatter.writeLocal(writer, name, type, signature);
|
||||||
writer.write('"');
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -230,10 +230,10 @@ public class MethodDefinition {
|
|||||||
if (parameterName != null || annotations.size() != 0) {
|
if (parameterName != null || annotations.size() != 0) {
|
||||||
writer.write(".param p");
|
writer.write(".param p");
|
||||||
writer.printSignedIntAsDec(registerNumber);
|
writer.printSignedIntAsDec(registerNumber);
|
||||||
|
|
||||||
if (parameterName != null) {
|
if (parameterName != null) {
|
||||||
writer.write(", ");
|
writer.write(", ");
|
||||||
// TODO: does dalvik allow non-identifier parameter and/or local names?
|
ReferenceFormatter.writeStringReference(writer, parameterName);
|
||||||
writer.write(parameterName);
|
|
||||||
}
|
}
|
||||||
writer.write(" # ");
|
writer.write(" # ");
|
||||||
writer.write(parameterType);
|
writer.write(parameterType);
|
||||||
|
@ -76,6 +76,11 @@ public class AnalysisTest {
|
|||||||
runTest("DuplicateTest", false);
|
runTest("DuplicateTest", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void LocalTest() throws IOException, URISyntaxException {
|
||||||
|
runTest("LocalTest", false);
|
||||||
|
}
|
||||||
|
|
||||||
public void runTest(String test, boolean registerInfo) throws IOException, URISyntaxException {
|
public void runTest(String test, boolean registerInfo) throws IOException, URISyntaxException {
|
||||||
String dexFilePath = String.format("%s%sclasses.dex", test, File.separatorChar);
|
String dexFilePath = String.format("%s%sclasses.dex", test, File.separatorChar);
|
||||||
|
|
||||||
|
31
baksmali/src/test/resources/LocalTest/LocalTest.smali
Normal file
31
baksmali/src/test/resources/LocalTest/LocalTest.smali
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
.class public LLocalTest;
|
||||||
|
.super Ljava/lang/Object;
|
||||||
|
|
||||||
|
|
||||||
|
# direct methods
|
||||||
|
.method public static method1()V
|
||||||
|
.registers 10
|
||||||
|
|
||||||
|
.local v0, "blah! This local name has some spaces, a colon, even a \nnewline!":I, "some sig info:\nblah."
|
||||||
|
.local v1, "blah! This local name has some spaces, a colon, even a \nnewline!":V, "some sig info:\nblah."
|
||||||
|
.local v2, "blah! This local name has some spaces, a colon, even a \nnewline!":I
|
||||||
|
.local v3, "blah! This local name has some spaces, a colon, even a \nnewline!":V
|
||||||
|
.local v4, null:I, "some sig info:\nblah."
|
||||||
|
.local v5, null:V, "some sig info:\nblah."
|
||||||
|
.local v6, null:I
|
||||||
|
.local v7
|
||||||
|
.local v8
|
||||||
|
.local v9
|
||||||
|
return-void
|
||||||
|
.end method
|
||||||
|
|
||||||
|
.method public static method2(IJLjava/lang/String;)V
|
||||||
|
.registers 10
|
||||||
|
.param p0, "blah! This local name has some spaces, a colon, even a \nnewline!" # I
|
||||||
|
.param p1 # J
|
||||||
|
.annotation runtime LAnnotationWithValues;
|
||||||
|
.end annotation
|
||||||
|
.end param
|
||||||
|
|
||||||
|
return-void
|
||||||
|
.end method
|
BIN
baksmali/src/test/resources/LocalTest/classes.dex
Normal file
BIN
baksmali/src/test/resources/LocalTest/classes.dex
Normal file
Binary file not shown.
@ -762,13 +762,13 @@ the annotations. If it turns out that they are parameter annotations, we include
|
|||||||
add them to the $statements_and_directives::methodAnnotations list*/
|
add them to the $statements_and_directives::methodAnnotations list*/
|
||||||
parameter_directive
|
parameter_directive
|
||||||
@init {List<CommonTree> annotations = new ArrayList<CommonTree>();}
|
@init {List<CommonTree> annotations = new ArrayList<CommonTree>();}
|
||||||
: PARAMETER_DIRECTIVE REGISTER COMMA simple_name
|
: PARAMETER_DIRECTIVE REGISTER (COMMA STRING_LITERAL)?
|
||||||
({input.LA(1) == ANNOTATION_DIRECTIVE}? annotation {annotations.add($annotation.tree);})*
|
({input.LA(1) == ANNOTATION_DIRECTIVE}? annotation {annotations.add($annotation.tree);})*
|
||||||
|
|
||||||
( END_PARAMETER_DIRECTIVE
|
( END_PARAMETER_DIRECTIVE
|
||||||
-> ^(I_PARAMETER[$start, "I_PARAMETER"] REGISTER simple_name ^(I_ANNOTATIONS annotation*))
|
-> ^(I_PARAMETER[$start, "I_PARAMETER"] REGISTER STRING_LITERAL? ^(I_ANNOTATIONS annotation*))
|
||||||
| /*epsilon*/ {$statements_and_directives::methodAnnotations.addAll(annotations);}
|
| /*epsilon*/ {$statements_and_directives::methodAnnotations.addAll(annotations);}
|
||||||
-> ^(I_PARAMETER[$start, "I_PARAMETER"] REGISTER simple_name ^(I_ANNOTATIONS))
|
-> ^(I_PARAMETER[$start, "I_PARAMETER"] REGISTER STRING_LITERAL? ^(I_ANNOTATIONS))
|
||||||
);
|
);
|
||||||
|
|
||||||
ordered_debug_directive
|
ordered_debug_directive
|
||||||
@ -785,8 +785,10 @@ line_directive
|
|||||||
-> ^(I_LINE[$start, "I_LINE"] integral_literal I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
|
-> ^(I_LINE[$start, "I_LINE"] integral_literal I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
|
||||||
|
|
||||||
local_directive
|
local_directive
|
||||||
: LOCAL_DIRECTIVE REGISTER COMMA simple_name COLON nonvoid_type_descriptor (COMMA STRING_LITERAL)?
|
: LOCAL_DIRECTIVE REGISTER (COMMA (NULL_LITERAL | name=STRING_LITERAL) COLON (VOID_TYPE | nonvoid_type_descriptor)
|
||||||
-> ^(I_LOCAL[$start, "I_LOCAL"] REGISTER simple_name nonvoid_type_descriptor STRING_LITERAL? I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
|
(COMMA signature=STRING_LITERAL)? )?
|
||||||
|
-> ^(I_LOCAL[$start, "I_LOCAL"] REGISTER NULL_LITERAL? $name? nonvoid_type_descriptor? $signature?
|
||||||
|
I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
|
||||||
|
|
||||||
end_local_directive
|
end_local_directive
|
||||||
: END_LOCAL_DIRECTIVE REGISTER
|
: END_LOCAL_DIRECTIVE REGISTER
|
||||||
|
@ -612,7 +612,7 @@ parameters[List<SmaliMethodParameter> parameters]
|
|||||||
: ^(I_PARAMETERS (parameter[parameters])*);
|
: ^(I_PARAMETERS (parameter[parameters])*);
|
||||||
|
|
||||||
parameter[List<SmaliMethodParameter> parameters]
|
parameter[List<SmaliMethodParameter> parameters]
|
||||||
: ^(I_PARAMETER REGISTER SIMPLE_NAME annotations)
|
: ^(I_PARAMETER REGISTER string_literal? annotations)
|
||||||
{
|
{
|
||||||
final int registerNumber = parseRegister_short($REGISTER.text);
|
final int registerNumber = parseRegister_short($REGISTER.text);
|
||||||
int totalMethodRegisters = $method::totalMethodRegisters;
|
int totalMethodRegisters = $method::totalMethodRegisters;
|
||||||
@ -639,7 +639,7 @@ parameter[List<SmaliMethodParameter> parameters]
|
|||||||
}
|
}
|
||||||
|
|
||||||
SmaliMethodParameter methodParameter = parameters.get(parameterIndex);
|
SmaliMethodParameter methodParameter = parameters.get(parameterIndex);
|
||||||
methodParameter.name = $SIMPLE_NAME.text;
|
methodParameter.name = $string_literal.value;
|
||||||
if ($annotations.annotations != null && $annotations.annotations.size() > 0) {
|
if ($annotations.annotations != null && $annotations.annotations.size() > 0) {
|
||||||
methodParameter.annotations = $annotations.annotations;
|
methodParameter.annotations = $annotations.annotations;
|
||||||
}
|
}
|
||||||
@ -665,12 +665,12 @@ line returns[DebugItem debugItem]
|
|||||||
};
|
};
|
||||||
|
|
||||||
local returns[DebugItem debugItem]
|
local returns[DebugItem debugItem]
|
||||||
: ^(I_LOCAL REGISTER SIMPLE_NAME nonvoid_type_descriptor string_literal? address)
|
: ^(I_LOCAL REGISTER ((NULL_LITERAL | name=string_literal) nonvoid_type_descriptor? signature=string_literal?)? address)
|
||||||
{
|
{
|
||||||
int registerNumber = parseRegister_short($REGISTER.text);
|
int registerNumber = parseRegister_short($REGISTER.text);
|
||||||
|
|
||||||
$debugItem = new ImmutableStartLocal($address.address, registerNumber, $SIMPLE_NAME.text,
|
$debugItem = new ImmutableStartLocal($address.address, registerNumber, $name.value,
|
||||||
$nonvoid_type_descriptor.type, $string_literal.value);
|
$nonvoid_type_descriptor.type, $signature.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
end_local returns[DebugItem debugItem]
|
end_local returns[DebugItem debugItem]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user