Skip to content

Disassembler

The disassembler API allows you to introspect and manipulate disassemblers in slicer. slicer offers several disassemblers/decompilers out of the box, but this API makes it possible to add custom ones via a script.

All disassembler operations are done via a DisassemblerContext, which you can once again access on the context.

context.disasm.all(); // lists all disassemblers
context.disasm.find("vf"); // finds a disassembler by its ID, returns null if not found; this example returns the Vineflower decompiler
// these operations do NOT persist and work only within the current instance of slicer
context.disasm.add({ ... }); // adds a custom disassembler
context.disasm.remove("vf"); // removes a disassembler by its ID

Every disassembler needs an ID and a class function that disassembles a class file byte array into a string representation. Optionally, a method function for disassembling a single method and human-readable label can also be supplied.

A disassembler can request class files from the workspace based on their internal names using the supplied source function.

const myDisasm /*: Disassembler */ = {
id: "my-disasm",
label: "My disassembler", // optional
language: "java", // optional
async class(
name /*: string */, // an internal name of the disassembled class, i.e. com/example/Main
source /*: (name: string) => (Uint8Array | null) | Promise<Uint8Array | null> */
) /*: string | Promise<string> */ {
const data /*: Uint8Array | null */ = await source(name);
if (!data) return ""; // this should never happen
// disassembler logic goes here
},
// optional
async method(
name /*: string */, // an internal name of the disassembled class, i.e. com/example/Main
signature /*: string */, // a method name and descriptor joined together, i.e. main([Ljava/lang/String;)V
source /*: (name: string) => (Uint8Array | null) | Promise<Uint8Array | null> */
) /*: string | Promise<string> */ {
const data /*: Uint8Array | null */ = await source(name);
if (!data) return ""; // this should never happen
// disassembler logic goes here
},
};
export default {
// ...
load(context /*: ScriptContext */) {
context.disasm.add(myDisasm);
},
unload(context /*: ScriptContext */) {
context.disasm.remove(myDisasm.id);
},
};