in src/main/java/org/apache/bcel/util/CodeHTML.java [370:471]
private void findGotos(final ByteSequence bytes, final Code code) throws IOException {
int index;
gotoSet = new BitSet(bytes.available());
int opcode;
/*
* First get Code attribute from method and the exceptions handled (try .. catch) in this method. We only need the line
* number here.
*/
if (code != null) {
final CodeException[] ce = code.getExceptionTable();
for (final CodeException cex : ce) {
gotoSet.set(cex.getStartPC());
gotoSet.set(cex.getEndPC());
gotoSet.set(cex.getHandlerPC());
}
// Look for local variables and their range
final Attribute[] attributes = code.getAttributes();
for (final Attribute attribute : attributes) {
if (attribute.getTag() == Const.ATTR_LOCAL_VARIABLE_TABLE) {
((LocalVariableTable) attribute).forEach(var -> {
final int start = var.getStartPC();
gotoSet.set(start);
gotoSet.set(start + var.getLength());
});
break;
}
}
}
// Get target addresses from GOTO, JSR, TABLESWITCH, etc.
while (bytes.available() > 0) {
opcode = bytes.readUnsignedByte();
// System.out.println(getOpcodeName(opcode));
switch (opcode) {
case Const.TABLESWITCH:
case Const.LOOKUPSWITCH:
// bytes.readByte(); // Skip already read byte
final int remainder = bytes.getIndex() % 4;
final int noPadBytes = remainder == 0 ? 0 : 4 - remainder;
int defaultOffset;
int offset;
for (int j = 0; j < noPadBytes; j++) {
bytes.readByte();
}
// Both cases have a field default_offset in common
defaultOffset = bytes.readInt();
if (opcode == Const.TABLESWITCH) {
final int low = bytes.readInt();
final int high = bytes.readInt();
offset = bytes.getIndex() - 12 - noPadBytes - 1;
defaultOffset += offset;
gotoSet.set(defaultOffset);
for (int j = 0; j < high - low + 1; j++) {
index = offset + bytes.readInt();
gotoSet.set(index);
}
} else { // LOOKUPSWITCH
final int npairs = bytes.readInt();
offset = bytes.getIndex() - 8 - noPadBytes - 1;
defaultOffset += offset;
gotoSet.set(defaultOffset);
for (int j = 0; j < npairs; j++) {
// int match = bytes.readInt();
bytes.readInt();
index = offset + bytes.readInt();
gotoSet.set(index);
}
}
break;
case Const.GOTO:
case Const.IFEQ:
case Const.IFGE:
case Const.IFGT:
case Const.IFLE:
case Const.IFLT:
case Const.IFNE:
case Const.IFNONNULL:
case Const.IFNULL:
case Const.IF_ACMPEQ:
case Const.IF_ACMPNE:
case Const.IF_ICMPEQ:
case Const.IF_ICMPGE:
case Const.IF_ICMPGT:
case Const.IF_ICMPLE:
case Const.IF_ICMPLT:
case Const.IF_ICMPNE:
case Const.JSR:
// bytes.readByte(); // Skip already read byte
index = bytes.getIndex() + bytes.readShort() - 1;
gotoSet.set(index);
break;
case Const.GOTO_W:
case Const.JSR_W:
// bytes.readByte(); // Skip already read byte
index = bytes.getIndex() + bytes.readInt() - 1;
gotoSet.set(index);
break;
default:
bytes.unreadByte();
codeToHTML(bytes, 0); // Ignore output
}
}
}