ChipBench packages Ghidra, radare2, binwalk, chip-programming tools,
simulators, and firmware-unpacking utilities into one reproducible container
for analyzing raw chip dumps entirely from the command line or an AI CLI.
Headless Jython scripts drive import, forced-disassembly sweeps, live
queries, and bulk decompilation exports without any GUI.
Derived from a private engagement environment, generalized for public
release under AGPLv3. No engagement-specific artifacts are included.
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
57 lines
1.8 KiB
Python
57 lines
1.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
#
|
|
# Part of ChipBench (AGPLv3). SPDX-FileCopyrightText: 2026 Starting Line Productions LLC
|
|
# AutoFuncs.py -- create functions at every LCALL/LJMP target + scheduler
|
|
# jumptable entries, iterating until stable. Handles call tables (JMP @A+DPTR)
|
|
# where the table entries are LJMPs by treating table bodies as code.
|
|
from ghidra.program.model.address import AddressSet
|
|
from ghidra.app.cmd.function import CreateFunctionCmd
|
|
from ghidra.app.cmd.disassemble import DisassembleCommand
|
|
from ghidra.app.plugin.core.analysis import AutoAnalysisManager
|
|
|
|
prog = currentProgram
|
|
af = prog.getAddressFactory()
|
|
cs = af.getDefaultAddressSpace()
|
|
fm = prog.getFunctionManager()
|
|
mem = prog.getMemory()
|
|
|
|
def A(x): return cs.getAddress(x)
|
|
|
|
def mk(a):
|
|
if a < 0x10000 and fm.getFunctionAt(a) is None:
|
|
CreateFunctionCmd(a).applyTo(prog, monitor)
|
|
|
|
rounds = 0
|
|
prev = -1
|
|
while rounds < 4:
|
|
n = 0
|
|
for i in range(0x0000, 0xEE00):
|
|
try:
|
|
b = mem.getByte(A(i)) & 0xFF
|
|
except:
|
|
continue
|
|
if b == 0x12 or b == 0x02: # LCALL/LJMP
|
|
try:
|
|
hi = mem.getByte(A(i+1)) & 0xFF
|
|
lo = mem.getByte(A(i+2)) & 0xFF
|
|
except:
|
|
continue
|
|
t = (hi << 8) | lo
|
|
if 0x0008 <= t < 0xEE00:
|
|
if fm.getFunctionAt(A(t)) is None:
|
|
if CreateFunctionCmd(A(t)).applyTo(prog, monitor):
|
|
n += 1
|
|
# reanalyze
|
|
mgr = AutoAnalysisManager.getAnalysisManager(prog)
|
|
mgr.reAnalyzeAll(None)
|
|
mgr.startAnalysis(monitor)
|
|
cur = fm.getFunctionCount()
|
|
print("round %d: +%d new, total %d" % (rounds, n, cur))
|
|
if cur == prev:
|
|
break
|
|
prev = cur
|
|
rounds += 1
|
|
|
|
print("AutoFuncs done: %d functions, %d instructions" % (
|
|
fm.getFunctionCount(), prog.getListing().getNumInstructions()))
|