Skip to content

Commit

Permalink
Merge branch 'master' of github.com:leibnitz27/cfr
Browse files Browse the repository at this point in the history
  • Loading branch information
leibnitz27 committed Dec 9, 2021
2 parents ca22319 + 48d5129 commit 9e917b3
Show file tree
Hide file tree
Showing 14 changed files with 178 additions and 142 deletions.
3 changes: 3 additions & 0 deletions developer_docs/building.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ Just ensure you have <a href="https://maven.apache.org/">maven</a> installed.

Then `mvn compile` in the root will get you what you need.

Note: if you encounter a `maven-compiler-plugin...: Compilation failure` error while trying to compile the project then your `JAVA_HOME` environment variable is probably pointing to a JDK version that doesn't support `6` for the `source` or `target` compile options.
Fix this by pointing `JAVA_HOME` to a JDK version that still supports compiling to java 1.6 such as JDK 10 (successfully tested). Also note, the version of java on your `path` may need to be greater than 1.6 if you are using `maven` version `>=3.3.1` which requires java 1.7. The best solution is to use JDK 8, 9, or 10 for both your `path` and `JAVA_HOME`

The main class is `org.benf.cfr.reader.Main`, so once you've built, you can test it out (from `target/classes`)

`java org.benf.cfr.reader.Main java.lang.Object`
Expand Down
5 changes: 5 additions & 0 deletions src/org/benf/cfr/reader/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ public static void main(String[] args) {
return;
}

if (options.optionIsSet(OptionsImpl.VERSION)) {
getOptParser.showVersion();
return;
}

CfrDriver cfrDriver = new CfrDriver.Builder().withBuiltOptions(options).build();
cfrDriver.analyse(files);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,13 @@ private static boolean pushPreChange(Op03SimpleStatement preChange, boolean back
Expression lvalueExpression = new LValueExpression(mutatedLValue);
UsageWatcher usageWatcher = new UsageWatcher(mutatedLValue);

Op03SimpleStatement lastCurr = null;
while (true) {
if (lastCurr == current) return false;
List<Op03SimpleStatement> candidates = back ? current.getSources() : current.getTargets();
if (candidates.size() != 1) return false;

lastCurr = current;
current = candidates.get(0);
/*
* If current makes use of x in any way OTHER than a simple assignment, we have to abort.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,34 @@ public void rewind1() {
if (idx > 0) idx--;
}

/*
* toString on this should only be visible during diagnostics.
* don't dump too much, as this can be used on *very* large data.
*/
@Override
public String toString() {
if (data == null) return "Null data!"; // precondition fail.
if (isFinished()) return "Finished";
T t = data.get(idx);
return t == null ? "null" : t.toString();

StringBuilder sb = new StringBuilder();
int dumpIdx = idx;
sb.append(idx).append("/").append(data.size()).append(" ");
if (dumpIdx == -1) {
sb.append("(not yet advanced)");
dumpIdx = 0;
}
int start = Math.max(0, dumpIdx - 3);
int end = Math.min(data.size(), dumpIdx + 3);
sb.append("[");
if (start > 0) sb.append("...");
for (int i = start; i < end; i++) {
if (i != start) sb.append(",");
T t = data.get(i);
sb.append(i).append("#").append(t.getClass().getSimpleName()).append("@").append(Integer.toHexString(t.hashCode()));
}
if (end < data.size()) sb.append("...");
sb.append("]");
return sb.toString();
}

public void rewind() {
Expand Down
67 changes: 40 additions & 27 deletions src/org/benf/cfr/reader/entities/Field.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,39 +97,52 @@ private AttributeSignature getSignatureAttribute() {
return attributes.getByName(AttributeSignature.ATTRIBUTE_NAME);
}

public JavaTypeInstance getJavaTypeInstance() {
if (cachedDecodedType == null) {
AttributeSignature sig = getSignatureAttribute();
ConstantPoolEntryUTF8 signature = sig == null ? null : sig.getSignature();
ConstantPoolEntryUTF8 descriptor = cp.getUTF8Entry(descriptorIndex);
JavaTypeInstance sigType = null;
JavaTypeInstance desType;
if (signature != null) {
try {
sigType = ConstantPoolUtils.decodeTypeTok(signature.getValue(), cp);
} catch (Exception e) {
// ignore.
}
}
private JavaTypeInstance generateTypeInstance() {
AttributeSignature sig = getSignatureAttribute();
ConstantPoolEntryUTF8 signature = sig == null ? null : sig.getSignature();
ConstantPoolEntryUTF8 descriptor = cp.getUTF8Entry(descriptorIndex);
JavaTypeInstance sigType = null;
JavaTypeInstance desType;
if (signature != null) {
try {
desType = ConstantPoolUtils.decodeTypeTok(descriptor.getValue(), cp);
} catch (RuntimeException e) {
if (sigType == null) {
throw e;
sigType = ConstantPoolUtils.decodeTypeTok(signature.getValue(), cp);
if (sigType != null) {
// TODO : Ideally, we wouldn't return early here, and we would verify the signature type against
// the descriptor type. But that means we need to have a generic type binder for the field.
// That's ok, but inner classes make this quite expensive. For now, return.
return sigType;
}
desType = sigType;
} catch (Exception e) {
// ignore.
}
}

if (sigType != null) {
if (sigType.getDeGenerifiedType().equals(desType.getDeGenerifiedType())) {
cachedDecodedType = sigType;
} else {
// someone lied....
cachedDecodedType = desType;
}

try {
desType = ConstantPoolUtils.decodeTypeTok(descriptor.getValue(), cp);
} catch (RuntimeException e) {
if (sigType == null) {
throw e;
}
desType = sigType;
}

if (sigType != null) {
if (sigType.getDeGenerifiedType().equals(desType.getDeGenerifiedType())) {
return sigType;
} else {
cachedDecodedType = desType;
// someone lied....
// TODO : This might not be a lie if the field is a generic placeholder.
return desType;
}
} else {
return desType;
}
}

public JavaTypeInstance getJavaTypeInstance() {
if (cachedDecodedType == null) {
cachedDecodedType = generateTypeInstance();
}
return cachedDecodedType;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.benf.cfr.reader.entities.classfilehelpers;

import org.benf.cfr.reader.bytecode.analysis.types.ClassSignature;
import org.benf.cfr.reader.bytecode.analysis.types.InnerClassInfoUtils;
import org.benf.cfr.reader.bytecode.analysis.types.JavaRefTypeInstance;
import org.benf.cfr.reader.bytecode.analysis.types.JavaTypeInstance;
Expand Down Expand Up @@ -91,6 +92,22 @@ void dumpTopHeader(ClassFile classFile, Dumper d, boolean showPackage) {
}
}

protected void dumpImplements(Dumper d, ClassSignature signature) {
List<JavaTypeInstance> interfaces = signature.getInterfaces();
if (!interfaces.isEmpty()) {
d.keyword("implements ");
int size = interfaces.size();
for (int x = 0; x < size; ++x) {
JavaTypeInstance iface = interfaces.get(x);
d.dump(iface).separator((x < (size - 1) ? "," : "")).newln();
}
}
}

protected void dumpPermitted(ClassFile c, Dumper d) {
c.dumpPermitted(d);
}

void dumpImports(Dumper d, ClassFile classFile) {
/*
* It's a bit irritating that we have to check obfuscations here, but we are stripping unused types,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,8 @@ private void dumpHeader(ClassFile c, InnerClassDumpType innerClassDumpType, Dump
}
}

List<JavaTypeInstance> interfaces = signature.getInterfaces();
if (!interfaces.isEmpty()) {
d.keyword("implements ");
int size = interfaces.size();
for (int x = 0; x < size; ++x) {
JavaTypeInstance iface = interfaces.get(x);
d.dump(iface).separator((x < (size - 1) ? "," : "")).newln();
}
}
c.dumpPermitted(d);
dumpImplements(d, signature);
dumpPermitted(c, d);
d.removePendingCarriageReturn().print(" ");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ public ClassFileDumperRecord(DCCommonState dcCommonState) {
private void dumpHeader(ClassFile c, InnerClassDumpType innerClassDumpType, Dumper d) {
d.keyword(getAccessFlagsString(c.getAccessFlags(), dumpableAccessFlagsClass));

d.keyword("record ").dump(c.getClassType()).print("(");
d.keyword("record ");
c.dumpClassIdentity(d);
d.print("(");
List<ClassFileField> fields = Functional.filter(c.getFields(), new Predicate<ClassFileField>() {
@Override
public boolean test(ClassFileField in) {
Expand All @@ -38,6 +40,7 @@ public boolean test(ClassFileField in) {
f.dumpAsRecord(d, c);
}
d.print(") ");
dumpImplements(d, c.getClassSignature());
}

@Override
Expand Down
82 changes: 48 additions & 34 deletions src/org/benf/cfr/reader/util/bytestream/AbstractBackedByteData.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,83 +2,97 @@

import org.benf.cfr.reader.util.ConfusedCFRException;

import java.io.DataInputStream;

public abstract class AbstractBackedByteData implements ByteData {
protected final byte[] d;

protected AbstractBackedByteData(byte[] data) {
this.d = data;
}

abstract DataInputStream rawDataAsStream(int offset, int length);
abstract int getRealOffset(int offset);

@Override
public int getS4At(long o) throws ConfusedCFRException {
// Let's find an EFFICIENT way to do this later!
DataInputStream dis = rawDataAsStream((int) o, 4);
int a = getRealOffset((int) o);
try {
return dis.readInt();
} catch (Exception e) {
return (((d[a] & 0xFF) << 24) | ((d[a + 1] & 0xFF) << 16) | ((d[a + 2] & 0xFF) << 8) | (d[a + 3] & 0xFF));
} catch (IndexOutOfBoundsException e) {
throw new ConfusedCFRException(e);
}
}

@Override
public double getDoubleAt(long o) throws ConfusedCFRException {
DataInputStream dis = rawDataAsStream((int) o, 8);
try {
return dis.readDouble();
} catch (Exception e) {
throw new ConfusedCFRException(e);
}
return Double.longBitsToDouble(getLongAt(o));
}

@Override
public float getFloatAt(long o) throws ConfusedCFRException {
DataInputStream dis = rawDataAsStream((int) o, 8);
try {
return dis.readFloat();
} catch (Exception e) {
throw new ConfusedCFRException(e);
}
return Float.intBitsToFloat(getS4At(o));
}

@Override
public long getLongAt(long o) throws ConfusedCFRException {
DataInputStream dis = rawDataAsStream((int) o, 8);
int a = getRealOffset((int) o);
try {
return dis.readLong();
} catch (Exception e) {
return (((long)(d[a + 0] & 0xFF) << 56) +
((long)(d[a + 1] & 0xFF) << 48) +
((long)(d[a + 2] & 0xFF) << 40) +
((long)(d[a + 3] & 0xFF) << 32) +
((long)(d[a + 4] & 0xFF) << 24) +
((d[a + 5] & 0xFF) << 16) +
((d[a + 6] & 0xFF) << 8) +
((d[a + 7] & 0xFF) << 0));
} catch (IndexOutOfBoundsException e) {
throw new ConfusedCFRException(e);
}
}

@Override
public short getS2At(long o) throws ConfusedCFRException {
// Let's find an EFFICIENT way to do this later!
DataInputStream dis = rawDataAsStream((int) o, 2);
int a = getRealOffset((int) o);
try {
return dis.readShort();
} catch (Exception e) {
return (short)(((d[a] & 0xFF) << 8) | (d[a + 1] & 0xFF));
} catch (IndexOutOfBoundsException e) {
throw new ConfusedCFRException(e);
}
}

@Override
public int getU2At(long o) throws ConfusedCFRException {
// Let's find an EFFICIENT way to do this later!
DataInputStream dis = rawDataAsStream((int) o, 2);
int a = getRealOffset((int) o);
try {
return dis.readUnsignedShort();
} catch (Exception e) {
return (((d[a] & 0xFF) << 8) | (d[a + 1] & 0xFF));
} catch (IndexOutOfBoundsException e) {
throw new ConfusedCFRException(e);
}
}

@Override
public short getU1At(long o) throws ConfusedCFRException {
// Let's find an EFFICIENT way to do this later!
DataInputStream dis = rawDataAsStream((int) o, 1);
int a = getRealOffset((int) o);
try {
return (short) dis.readUnsignedByte();
} catch (Exception e) {
return (short)(d[a] & 0xff);
} catch (IndexOutOfBoundsException e) {
throw new ConfusedCFRException(e);
}
}

@Override
public byte getS1At(long o) {
int a = getRealOffset((int) o);
try {
return d[a];
} catch (IndexOutOfBoundsException e) {
throw new ConfusedCFRException(e);
}
}

@Override
public byte[] getBytesAt(int count, long offset) {
int a = getRealOffset((int) offset);
byte[] res = new byte[count];
System.arraycopy(d, a, res, 0, count);
return res;
}
}
28 changes: 6 additions & 22 deletions src/org/benf/cfr/reader/util/bytestream/BaseByteData.java
Original file line number Diff line number Diff line change
@@ -1,39 +1,23 @@
package org.benf.cfr.reader.util.bytestream;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;

public class BaseByteData extends AbstractBackedByteData {
private final byte[] data;

public BaseByteData(byte[] data) {
this.data = data;
}

@Override
public DataInputStream rawDataAsStream(int start, int len) {
return new DataInputStream(new ByteArrayInputStream(data, start, len));
super(data);
}

@Override
public ByteData getOffsetData(long offset) {
return new OffsetBackedByteData(data, offset);
return new OffsetBackedByteData(d, offset);
}

@Override
public OffsettingByteData getOffsettingOffsetData(long offset) {
return new OffsettingBackedByteData(data, offset);
}

@Override
public byte[] getBytesAt(int count, long offset) {
byte[] res = new byte[count];
System.arraycopy(data, (int) offset, res, 0, count);
return res;
return new OffsettingBackedByteData(d, offset);
}

@Override
public byte getS1At(long o) {
return data[(int) o];
int getRealOffset(int offset) {
return offset;
}

}
Loading

0 comments on commit 9e917b3

Please sign in to comment.