Improve the way multi-pass transformers are written #64

Open
opened 4 years ago by gpe · 0 comments
gpe commented 4 years ago
Owner

The current callback-based approach isn't really amenable to multiple passes. In some transformers we put too much logic in preTransform() and postTransform().

One idea is for each transformer to just override a single method again, and then call methods that accept lambdas - like forEachField { ... }, forEachInsnList { ... }, etc.

Or perhaps provide methods that return a Sequence<T>. It isn't yet obvious what T would be (e.g. for a field we'd actually want the FieldNode, ClassNode and Library, so Sequence<FieldNode> isn't good enough). This would be useful for transformers that need to find a single method or group of fields (e.g. the opaque predicate transformer finding the control fields) as methods like filter() could be used.

What should these methods be defined on? The ClassPath object?

Another idea is separate Pass classes, with each Transformer being a list of passes. I'm not sure how we'd pass data between them. e.g. we could have Pass<I, O> with the first pass having I=Unit and the last pass having O=Unit, and the I/O types matching up between adjacent passes? Encoding that in the type system is probably difficult though.

The current callback-based approach isn't really amenable to multiple passes. In some transformers we put too much logic in `preTransform()` and `postTransform()`. One idea is for each transformer to just override a single method again, and then call methods that accept lambdas - like `forEachField { ... }`, `forEachInsnList { ... }`, etc. Or perhaps provide methods that return a `Sequence<T>`. It isn't yet obvious what T would be (e.g. for a field we'd actually want the `FieldNode`, `ClassNode` and `Library`, so `Sequence<FieldNode>` isn't good enough). This would be useful for transformers that need to find a single method or group of fields (e.g. the opaque predicate transformer finding the control fields) as methods like `filter()` could be used. What should these methods be defined on? The `ClassPath` object? Another idea is separate `Pass` classes, with each `Transformer` being a list of passes. I'm not sure how we'd pass data between them. e.g. we could have `Pass<I, O>` with the first pass having `I=Unit` and the last pass having `O=Unit`, and the `I`/`O` types matching up between adjacent passes? Encoding that in the type system is probably difficult though.
gpe added the
deobfuscator
label 4 years ago
gpe added
asm
and removed
deobfuscator
labels 4 years ago
gpe added the
improvement
label 4 years ago
Sign in to join this conversation.
Loading…
There is no content yet.