CodeObserverpublic class CodeObserver extends Object implements BytecodeArray.VisitorBytecode visitor to use when "observing" bytecode getting parsed. |
Fields Summary |
---|
private final com.android.dx.util.ByteArray | bytesnon-null; actual array of bytecode | private final com.android.dx.cf.iface.ParseObserver | observernon-null; observer to inform of parsing |
Constructors Summary |
---|
public CodeObserver(com.android.dx.util.ByteArray bytes, com.android.dx.cf.iface.ParseObserver observer)Constructs an instance.
if (bytes == null) {
throw new NullPointerException("bytes == null");
}
if (observer == null) {
throw new NullPointerException("observer == null");
}
this.bytes = bytes;
this.observer = observer;
|
Methods Summary |
---|
public int | getPreviousOffset(){@inheritDoc}
return -1;
| private java.lang.String | header(int offset)Helper to produce the first bit of output for each instruction.
/*
* Note: This uses the original bytecode, not the
* possibly-transformed one.
*/
int opcode = bytes.getUnsignedByte(offset);
String name = ByteOps.opName(opcode);
if (opcode == ByteOps.WIDE) {
opcode = bytes.getUnsignedByte(offset + 1);
name += " " + ByteOps.opName(opcode);
}
return Hex.u2(offset) + ": " + name;
| public void | setPreviousOffset(int offset){@inheritDoc}
// Do nothing
| public void | visitBranch(int opcode, int offset, int length, int target){@inheritDoc}
String targetStr = (length <= 3) ? Hex.u2(target) : Hex.u4(target);
observer.parsed(bytes, offset, length,
header(offset) + " " + targetStr);
| public void | visitConstant(int opcode, int offset, int length, com.android.dx.rop.cst.Constant cst, int value){@inheritDoc}
if (cst instanceof CstKnownNull) {
// This is aconst_null.
visitNoArgs(opcode, offset, length, null);
return;
}
if (cst instanceof CstInteger) {
visitLiteralInt(opcode, offset, length, value);
return;
}
if (cst instanceof CstLong) {
visitLiteralLong(opcode, offset, length,
((CstLong) cst).getValue());
return;
}
if (cst instanceof CstFloat) {
visitLiteralFloat(opcode, offset, length,
((CstFloat) cst).getIntBits());
return;
}
if (cst instanceof CstDouble) {
visitLiteralDouble(opcode, offset, length,
((CstDouble) cst).getLongBits());
return;
}
String valueStr = "";
if (value != 0) {
valueStr = ", ";
if (opcode == ByteOps.MULTIANEWARRAY) {
valueStr += Hex.u1(value);
} else {
valueStr += Hex.u2(value);
}
}
observer.parsed(bytes, offset, length,
header(offset) + " " + cst + valueStr);
| public void | visitInvalid(int opcode, int offset, int length){@inheritDoc}
observer.parsed(bytes, offset, length, header(offset));
| private void | visitLiteralDouble(int opcode, int offset, int length, long bits)Helper for {code #visitConstant} where the constant is a
double .
String optArg = (length != 1) ? " #" + Hex.u8(bits) : "";
observer.parsed(bytes, offset, length,
header(offset) + optArg + " // " +
Double.longBitsToDouble(bits));
| private void | visitLiteralFloat(int opcode, int offset, int length, int bits)Helper for {code #visitConstant} where the constant is a
float .
String optArg = (length != 1) ? " #" + Hex.u4(bits) : "";
observer.parsed(bytes, offset, length,
header(offset) + optArg + " // " +
Float.intBitsToFloat(bits));
| private void | visitLiteralInt(int opcode, int offset, int length, int value)Helper for {code #visitConstant} where the constant is an
int .
String commentOrSpace = (length == 1) ? " // " : " ";
String valueStr;
opcode = bytes.getUnsignedByte(offset); // Compare with orig op below.
if ((length == 1) || (opcode == ByteOps.BIPUSH)) {
valueStr = "#" + Hex.s1(value);
} else if (opcode == ByteOps.SIPUSH) {
valueStr = "#" + Hex.s2(value);
} else {
valueStr = "#" + Hex.s4(value);
}
observer.parsed(bytes, offset, length,
header(offset) + commentOrSpace + valueStr);
| private void | visitLiteralLong(int opcode, int offset, int length, long value)Helper for {code #visitConstant} where the constant is a
long .
String commentOrLit = (length == 1) ? " // " : " #";
String valueStr;
if (length == 1) {
valueStr = Hex.s1((int) value);
} else {
valueStr = Hex.s8(value);
}
observer.parsed(bytes, offset, length,
header(offset) + commentOrLit + valueStr);
| public void | visitLocal(int opcode, int offset, int length, int idx, com.android.dx.rop.type.Type type, int value){@inheritDoc}
String idxStr = (length <= 3) ? Hex.u1(idx) : Hex.u2(idx);
boolean argComment = (length == 1);
String valueStr = "";
if (opcode == ByteOps.IINC) {
valueStr = ", #" +
((length <= 3) ? Hex.s1(value) : Hex.s2(value));
}
String catStr = "";
if (type.isCategory2()) {
catStr = (argComment ? "," : " //") + " category-2";
}
observer.parsed(bytes, offset, length,
header(offset) + (argComment ? " // " : " ") +
idxStr + valueStr + catStr);
| public void | visitNewarray(int offset, int length, com.android.dx.rop.cst.CstType cst, java.util.ArrayList intVals){@inheritDoc}
String commentOrSpace = (length == 1) ? " // " : " ";
String typeName = cst.getClassType().getComponentType().toHuman();
observer.parsed(bytes, offset, length,
header(offset) + commentOrSpace + typeName);
| public void | visitNoArgs(int opcode, int offset, int length, com.android.dx.rop.type.Type type){@inheritDoc}
observer.parsed(bytes, offset, length, header(offset));
| public void | visitSwitch(int opcode, int offset, int length, com.android.dx.cf.code.SwitchList cases, int padding){@inheritDoc}
int sz = cases.size();
StringBuffer sb = new StringBuffer(sz * 20 + 100);
sb.append(header(offset));
if (padding != 0) {
sb.append(" // padding: " + Hex.u4(padding));
}
sb.append('\n");
for (int i = 0; i < sz; i++) {
sb.append(" ");
sb.append(Hex.s4(cases.getValue(i)));
sb.append(": ");
sb.append(Hex.u2(cases.getTarget(i)));
sb.append('\n");
}
sb.append(" default: ");
sb.append(Hex.u2(cases.getDefaultTarget()));
observer.parsed(bytes, offset, length, sb.toString());
|
|