diff --git a/README.md b/README.md index 444ebdd..4c1cf2d 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ Some components will allow specifying extended format strings for data to be log * `result`: Call result if available * `this`: Instance reference * `argNN`: Argument value where NN is the argument’s zero-based position +* `args`: Comma-separated list of all arguments (stringified) In addition, the format specifier `%x` is treated specially: `System.identityHashCode()` will be called on the corresponding input and the result hex-formatted. @@ -74,6 +75,7 @@ Configuration options: * `MethodLogger.enabled`: add to enable this component * `MethodLogger.filter`: (optional) restricts functionality to a set of methods, for value format see Method filters section above * `MethodLogger.tag`: (optional) log tag to be used (default is `MethodLogger`) +* `MethodLogger.format`: (optional) extended format string to be used, see Extended format strings section above (default is `Entered method {method:%s} ({args:%s})`) ## AssignmentRemover component diff --git a/src/info/palant/apkInstrumentation/MethodLogger.java b/src/info/palant/apkInstrumentation/MethodLogger.java index e88fd18..ef19bd0 100644 --- a/src/info/palant/apkInstrumentation/MethodLogger.java +++ b/src/info/palant/apkInstrumentation/MethodLogger.java @@ -6,19 +6,19 @@ package info.palant.apkInstrumentation; -import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.stream.Collectors; import soot.Body; import soot.BodyTransformer; -import soot.Local; -import soot.jimple.StringConstant; +import soot.Value; public class MethodLogger extends BodyTransformer { private final MethodConfig filter; private String tag; + private String format; public MethodLogger(Properties config) { @@ -31,6 +31,10 @@ public MethodLogger(Properties config) this.tag = config.getProperty("MethodLogger.tag"); if (tag == null) this.tag = "MethodLogger"; + + this.format = config.getProperty("MethodLogger.format"); + if (this.format == null) + this.format = "Entered method {method:%s} ({args:%s})"; } @Override @@ -40,31 +44,12 @@ protected void internalTransform(Body body, String phaseName, Map parameters = body.getParameterLocals(); - if (parameters.size() > 0) - { - Local message = units.newObject( - "java.lang.StringBuilder", - StringConstant.v("Entered method " + body.getMethod().getSignature() + " with parameters: ") - ); - - boolean first = true; - for (Local parameter: parameters) - { - if (first) - first = false; - else - units.call(message, "append", StringConstant.v(", ")); - - units.call(message, "append", units.stringify(parameter)); - } - - units.log(this.tag, units.stringify(message)); - } - else - units.log(this.tag, StringConstant.v("Entered method " + body.getMethod().getSignature())); - + units.log(this.tag, units.extendedFormat( + this.format, + null, + body.getThisLocal(), + body.getParameterLocals().stream().map(local -> (Value)local).collect(Collectors.toList()) + )); units.insertBefore(); } } diff --git a/src/info/palant/apkInstrumentation/UnitSequence.java b/src/info/palant/apkInstrumentation/UnitSequence.java index c14aebc..d2763fe 100644 --- a/src/info/palant/apkInstrumentation/UnitSequence.java +++ b/src/info/palant/apkInstrumentation/UnitSequence.java @@ -245,6 +245,30 @@ else if (matcher.group(1).equals("result")) arg = result; else if (matcher.group(1).equals("this")) arg = thisRef; + else if (matcher.group(1).equals("args")) + { + if (argValues.size() == 0) + arg = StringConstant.v(""); + else if (argValues.size() == 1) + arg = this.stringify(argValues.get(0)); + else + { + Local builder = this.newObject("java.lang.StringBuilder"); + + boolean first = true; + for (Value argValue: argValues) + { + if (first) + first = false; + else + this.call(builder, "append", StringConstant.v(", ")); + + this.call(builder, "append", this.stringify(argValue)); + } + + arg = this.stringify(builder); + } + } else if (matcher.group(1).startsWith("arg")) arg = argValues.get(Integer.parseInt(matcher.group(1).substring(3))); else