docs.sheetjs.com/docz/static/ghidra/sheetjs-ghidra.js

71 lines
2.7 KiB
JavaScript

const { utils: { book_new, json_to_sheet }, writeFileXLSX } = require("xlsx");
/* start decompiler */
const DecompInterface = JavaHelper.getClass('ghidra.app.decompiler.DecompInterface');
const decompiler = new DecompInterface();
decompiler.openProgram(currentProgram);
/* get decompiled C source */
const src = (() => {
const fname = '_TSTCellToCellStorage';
/* find address to function */
const fsymbs = currentProgram.getSymbolTable().getGlobalSymbols(fname);
if(!fsymbs) throw new Error(`Global Symbol ${fname} cannot be found`);
/* find function */
const fn = currentProgram.getFunctionManager().getFunctionAt(fsymbs[0].getAddress());
if(!fn) throw new Error(`Function ${fname} cannot be found`);
/* decompile function */
const decomp = decompiler.decompileFunction(fn, 10000, null);
if (decomp.isTimedOut() || !decomp.decompileCompleted()) throw new Error(`Function ${fname} at ${fn} could not be decompiled`);
/* get and return generated C code */
const src = decomp.getDecompiledFunction().getC();
if(!src) throw new Error(`Function ${fname} at ${fn} decompilation`);
return src;
})();
/* offset[n] will be the name of the field at bit `n` (mask `1 << n`) */
let offset = [];
/* combine split lines and lazily extract data from C source */
let n = -1;
src.split(/[\r\n]+/).reduce((acc,row,i) => {
if(i <= 9) acc.rows.push(row);
else if(row.match(/[{};]$/)) {
if(acc.buf) { row = acc.buf + row.trim(); acc.buf = ""; }
acc.rows.push(row);
} else acc.buf += acc.buf ? row.trim() : row.replace(/[\r\n]+$/,"");
return acc;
}, {rows:[], buf:""}).rows.forEach(line => {
if(line.match(/^ if.*(char|short| >> | & )/)) {
n = -1;
if(!line.match(/Var/)) return;
if(line.match(/char/)) n = 7;
else if(line.match(/short/)) n = 15;
else if(line.match(/>>/)) n = parseInt(line.match(/>> ([1-9]\d*|0x[0-9a-f]+)/)[1]);
else if(line.match(/&/)) n = Math.round(Math.log2(parseInt(line.match(/& ([1-9]\d*|0x[0-9a-f]+)/)[1])));
} else if(line.match(/PTR__objc_msgSend/) && n >= 0) {
if(line.match(/AssertionHandler|NSString|stringWithUTF8String|Failure/)) return;
if(!line.match(/,/)) return; // suppress noop
const ptr = line.match(/PTR_s_\w+/)[0];
offset[+n] = ptr;
n = -1;
}
});
/* construct objects with "Mask" (hex string) and "Internal Name" */
const aoo = offset.map((name, idx) => ({
Mask: "0x" + (1 << idx).toString(16),
"Internal Name": name.replace(/^PTR_s_|_[0-9a-f]*$/g,"").replace(/[A-Z]/g, " $&").toLowerCase().replace(/ i d/, " ID")
}));
/* create worksheet */
const ws = json_to_sheet(aoo);
/* write workbook */
const wb = book_new(ws, "Offsets");
/* write to XLSX */
writeFileXLSX(wb, "SheetJSGhidraTSTCell.xlsx");