Skip to content

Commit 7dc0d83

Browse files
committed
Split up DownloadLogger component into more generic CallLogger and StreamLogger components
1 parent 55c9014 commit 7dc0d83

File tree

12 files changed

+442
-266
lines changed

12 files changed

+442
-266
lines changed

README.md

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,27 +32,48 @@ Each component has a `filter` option allowing to restrict its functionality. It
3232
* `com.example.test.Main`: includes all methods of a specific class
3333
* `com.example.test.Main.dump()`: includes all methods with a particular name inside a class (empty parentheses at the end are mandatory)
3434

35-
## MethodLogger component
35+
## Extended format strings
3636

37-
This component will add logging to the start of each method. In addition to the method signature, the parameter values will be logged.
37+
Some components will allow specifying extended format strings for data to be logged. These use the usual [Java format specifiers](https://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax) like `%s` or `%i` but require specifying the input as well, e.g. `{this:%s}` (format `this` value as a string) or `{arg2:%i}` (format second parameter as integer). The following input specifiers are possible:
38+
39+
* `method`: The signature of the calling method
40+
* `result`: Call result if available
41+
* `this`: Instance reference
42+
* `argNN`: Argument value where NN is the argument’s zero-based position
43+
44+
In addition, the format specifier `%x` is treated specially: `System.identityHashCode()` will be called on the corresponding input and the result hex-formatted.
45+
46+
## CallLogger component
47+
48+
This component will add logging code after calls to specified methods. See `config.properties.downloads` for a configuration example logging `URLConnection` interactions.
3849

3950
Configuration options:
4051

41-
* `MethodLogger.enabled`: add to enable this component
42-
* `MethodLogger.filter`: (optional) restricts functionality to a set of classes or methods (see Filters section above)
43-
* `MethodLogger.tag`: (optional) log tag to be used (default is `MethodLogger`)
52+
* `CallLogger.enabled`: add to enable this component
53+
* `CallLogger.filter`: (optional) restricts functionality to a set of classes or methods (see Filters section above)
54+
* `CallLogger.tag`: (optional) log tag to be used (default is `CallLogger`)
55+
* `CallLogger.<class>:<method>`: specifies a call to be logged. `<class>` has to be a full class name like `java.net.URL`. `<method>` can be either a method name like `openConnection` or a more specific method name along with parameter types like `getHeaderField(java.lang.String)`. The value is a format string (see Extended format strings section above).
4456

45-
## DownloadLogger component
57+
## StreamLogger component
4658

47-
This component will log `URLConnection` interactions.
59+
This component will wrap `InputStream` and `OutputStream` instances returned by specified methods to log data being sent or received. See `config.properties.downloads` for a configuration example logging streams returned by `URLConnection.getInputStream()` and `URLConnection.getOutputStream()`.
4860

4961
Configuration options:
5062

51-
* `DownloadLogger.enabled`: add to enable this component
52-
* `DownloadLogger.filter`: (optional) restricts functionality to a set of classes or methods (see Filters section above)
53-
* `DownloadLogger.tag`: (optional) log tag to be used (default is `DownloadLogger`)
54-
* `DownloadLogger.requestBodies`: (optional) if present, data sent via the connection will be logged
55-
* `DownloadLogger.responses`: (optional) if present, data received via the connection will be logged
63+
* `StreamLogger.enabled`: add to enable this component
64+
* `StreamLogger.filter`: (optional) restricts functionality to a set of classes or methods (see Filters section above)
65+
* `StreamLogger.tag`: (optional) log tag to be used (default is `StreamLogger`)
66+
* `StreamLogger.<class>:<method>`: specifies a call returning a stream that should be wrapped. `<class>` has to be a full class name like `java.net.URLConnection`. `<method>` can be either a method name like `getInputStream` or a more specific method name along with parameter types like `getOutputStream(java.net.URL)`. The value is a format string that will be used as a prefix for logged data (see Extended format strings section above).
67+
68+
## MethodLogger component
69+
70+
This component will add logging to the start of each method. In addition to the method signature, the parameter values will be logged.
71+
72+
Configuration options:
73+
74+
* `MethodLogger.enabled`: add to enable this component
75+
* `MethodLogger.filter`: (optional) restricts functionality to a set of classes or methods (see Filters section above)
76+
* `MethodLogger.tag`: (optional) log tag to be used (default is `MethodLogger`)
5677

5778
## AssignmentRemover component
5879

config.properties.downloads

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
sdk=/path/to/android/sdk
2+
input=game.apk
3+
output=game-instrumented.apk
4+
keystore=debug.jks
5+
keypass=123456
6+
7+
CallLogger.enabled = true
8+
CallLogger.java.net.URL\:openConnection = URLConnection {result:%x}: opened for URL {this:%s} (method {method:%s})
9+
CallLogger.java.net.URLConnection\:addRequestProperty(java.lang.String,java.lang.String) = URLConnection {this:%x}: added request header {arg0:%s}: {arg1:%s} (method {method:%s})
10+
CallLogger.java.net.URLConnection\:connect() = URLConnection {this:%x}: connected (method {method:%s})
11+
CallLogger.java.net.URLConnection\:getContentLength() = URLConnection {this:%x}: response content length is {result:%i} (method {method:%s})
12+
CallLogger.java.net.URLConnection\:getContentType() = URLConnection {this:%x}: response content type is {result:%s} (method {method:%s})
13+
CallLogger.java.net.URLConnection\:getHeaderField(java.lang.String) = URLConnection {this:%x}: header {arg0:%s} value is {result:%s} (method {method:%s})
14+
CallLogger.java.net.URLConnection\:setRequestProperty(java.lang.String,java.lang.String) = URLConnection {this:%x}: set request header {arg0:%s}: {arg1:%s} (method {method:%s})
15+
CallLogger.java.net.HttpURLConnection\:getResponseCode() = URLConnection {this:%x}: response code is {result:%i} (method {method:%s})
16+
CallLogger.java.net.HttpURLConnection\:setRequestMethod(java.lang.String) = URLConnection {this:%x}: request method set to {arg0:%s} (method {method:%s})
17+
18+
StreamLogger.enabled = true
19+
StreamLogger.java.net.URL\:openStream = URL {this:%s} response (requested by method {method:%s})
20+
StreamLogger.java.net.URLConnection\:getInputStream = URLConnection {this:%x}: response (requested by method {method:%s})
21+
StreamLogger.java.net.URLConnection\:getOutputStream = URLConnection {this:%x}: request body (requested by method {method:%s})
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* This Source Code is subject to the terms of the Mozilla Public License
3+
* version 2.0 (the "License"). You can obtain a copy of the License at
4+
* http://mozilla.org/MPL/2.0/.
5+
*/
6+
7+
package info.palant.apkInstrumentation;
8+
9+
import java.util.Map;
10+
import java.util.Properties;
11+
12+
import soot.Body;
13+
import soot.SootMethod;
14+
import soot.Unit;
15+
import soot.BodyTransformer;
16+
17+
public class CallLogger extends BodyTransformer
18+
{
19+
private final Filter filter;
20+
private String tag;
21+
private MethodConfig methodConfig;
22+
23+
public CallLogger(Properties config)
24+
{
25+
String filterSpec = config.getProperty("CallLogger.filter");
26+
if (filterSpec != null)
27+
this.filter = new Filter(filterSpec);
28+
else
29+
this.filter = null;
30+
31+
this.tag = config.getProperty("CallLogger.tag");
32+
if (tag == null)
33+
this.tag = "CallLogger";
34+
35+
this.methodConfig = new MethodConfig(config, "CallLogger.");
36+
}
37+
38+
@Override
39+
protected void internalTransform(Body body, String phaseName, Map<String, String> options)
40+
{
41+
if (this.filter != null && !this.filter.matches(body))
42+
return;
43+
44+
for (Unit unit: body.getUnits().toArray(new Unit[0]))
45+
{
46+
SootMethod method = UnitParser.getInvocationMethod(unit);
47+
if (method == null)
48+
continue;
49+
50+
String formatString = this.methodConfig.get(method);
51+
if (formatString == null)
52+
continue;
53+
54+
UnitSequence units = new UnitSequence(body);
55+
units.log(this.tag, units.extendedFormat(
56+
formatString,
57+
UnitParser.getAssignmentTarget(unit),
58+
UnitParser.getInvocationBase(unit),
59+
UnitParser.getInvocationArgs(unit)
60+
));
61+
units.insertAfter(unit);
62+
}
63+
}
64+
}

src/info/palant/apkInstrumentation/DownloadLogger.java

Lines changed: 0 additions & 234 deletions
This file was deleted.

0 commit comments

Comments
 (0)