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 disassemblerscontext.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 slicercontext.disasm.add({ ... }); // adds a custom disassemblercontext.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 version: "1.0.0", // optional language: "java", // optional options: {}, // a string-to-string mapping of applied disassembler options, modified by slicer and scripts, 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
const myOption = this.options?.["my-option"]; // 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
const myOption = this.options?.["my-option"]; // disassembler logic goes here },};
export default { // ... load(context /*: ScriptContext */) { context.disasm.add(myDisasm); }, unload(context /*: ScriptContext */) { context.disasm.remove(myDisasm.id); },};