forked from sheetjs/docs.sheetjs.com
71 lines
2.7 KiB
JavaScript
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");
|