Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Bytecode - ASM - Get Label Offset

I am trying to get the offsets of all labels in a method.

I tried using the following code:

private static ArrayList<Integer> GetLabelOffsets(MethodNode methodNode) {
    ArrayList<Integer> labelOffsets = new ArrayList<>();

    for (AbstractInsnNode instruction : methodNode.instructions.toArray()) {
        if (instruction instanceof JumpInsnNode) {
            JumpInsnNode jumpInsnNode = (JumpInsnNode) instruction;
            labelOffsets.add(jumpInsnNode.label.getLabel().getOffset());.
        }
    }

    return labelOffsets;
}

However the getOffset() method throws an Exception:

java.lang.IllegalStateException: Label offset position has not been resolved yet

How can I resolve these offset positions? Or what is the proper way to achieve this?

Edit

The MethodNode is an org.objectweb.asm.tree.MethodNode Object from the Java ASM library

Added more code at request:

public static HashMap<String, ClassNode> ParseJar(JarFile jar) {
    HashMap<String, ClassNode> classes = new HashMap<>();

    try {
        Enumeration<?> enumeration = jar.entries();
        while (enumeration.hasMoreElements()) {
            JarEntry entry = (JarEntry) enumeration.nextElement();

            if (entry.getName().endsWith(".class")) {
                ClassReader classReader = new ClassReader(jar.getInputStream(entry));
                ClassNode classNode = new ClassNode();
                classReader.accept(classNode, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
                classes.put(classNode.name, classNode);
            }

        }
        jar.close();
        return classes;
    } catch (Exception ex) {
        return null;
    }
}

public static void main(String[] args) {
    JarFile jar = new JarFile(fileName);
    HashMap<String, ClassNode> classes = JarUtils.ParseJar(jar);
    for (ClassNode classNode : classes.values()) {
        for (MethodNode methodNode : classNode.methods) {
            ArrayList<Integer> offsets = GetLabelOffsets(methodNode);
            // do more stuff with offsets
        }
    }
}
like image 885
eKKiM Avatar asked Jun 13 '26 14:06

eKKiM


1 Answers

From the documentation of getOffset():

This method is intended for Attribute sub classes, and is normally not needed by class generators or adapters.

Since this offset is defined in terms of bytes, it wouldn’t be very helpful when processing a list of instructions, especially as ASM abstracts the different forms of instructions that may have different lengths in byte code.

The general idea is that this instruction list can be changed, so Labels represent logical positions and the offset will be calculated when writing a method’s resulting bytecode and the actual numbers are known.

Within the instruction list, there should be a corresponding LabelNode referencing the same Label as the instruction.

like image 146
Holger Avatar answered Jun 18 '26 01:06

Holger



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!