Files
luma/Agent/core/memory.ts
Ole André Vadla Ravnås b092b17bc2 core: Fix disassembling what the map misses
Open through the r2 command so what it opens is mapped: the
disassembler skips whatever falls outside a map, and reading is not
enough. Drop the bin load, which only sniffed formats at address zero.

Let a failed read say so instead of returning null, remember the pages
that have none, and resolve an anchor live or not at all -- a stale
address lands on whatever occupies it now.
2026-09-10 16:30:19 +02:00

92 lines
1.9 KiB
TypeScript

type ModuleEventBatchMessage = {
type: "modules-changed";
added: Module[];
removed: Module[];
};
const addedByKey = new Map<string, Module>();
const removedByKey = new Map<string, Module>();
let flushScheduled = false;
let flushGeneration = 0;
export function readMemory(address: string, count: number): ArrayBuffer {
const bytes = ptr(address).readByteArray(count);
if (bytes === null) {
throw new Error(`Nothing mapped at ${address}`);
}
return bytes;
}
export function writeMemory(address: string, bytes: ArrayBuffer | number[]): number {
const buffer = bytes instanceof ArrayBuffer ? new Uint8Array(bytes) : new Uint8Array(bytes);
ptr(address).writeByteArray(Array.from(buffer));
return buffer.length;
}
Process.attachModuleObserver({
onAdded(module) {
const key = moduleKey(module);
if (removedByKey.has(key)) {
flushNow();
}
addedByKey.set(key, module);
scheduleFlush();
},
onRemoved(module) {
const key = moduleKey(module);
if (addedByKey.has(key)) {
flushNow();
}
removedByKey.set(key, module);
scheduleFlush();
},
});
function flushNow() {
if (addedByKey.size === 0 && removedByKey.size === 0) {
return;
}
const msg: ModuleEventBatchMessage = {
type: "modules-changed",
added: Array.from(addedByKey.values()),
removed: Array.from(removedByKey.values()),
};
addedByKey.clear();
removedByKey.clear();
flushGeneration++;
send(msg);
}
function scheduleFlush() {
if (flushScheduled) {
return;
}
flushScheduled = true;
const myGen = flushGeneration;
setImmediate(() => {
flushScheduled = false;
if (myGen !== flushGeneration) {
return;
}
flushNow();
});
}
function moduleKey(m: Module): string {
return m.base.toString();
}