mirror of
https://github.com/morluto/rea.git
synced 2026-11-06 23:06:18 +00:00
Share ELF note headers across note inspection, Flutter build IDs, Node SEA, and recorded-crash source binding. Decode REL/RELA records once for MIPS shared-load analysis and IL2CPP linking, removing superseded scalar helpers. Share the CLR header prefix between desktop detection and managed PE parsing while preserving their distinct read bounds and admission policies. Cover those differences and ignored R_NONE fields with production-boundary tests. Validation: 493 focused tests passed, two existing skips; static checks and test discovery passed. Public managed/desktop CLI and ELF notes CLI/MCP workflows exercised; no real external analysis providers were run.
83 lines
2.6 KiB
TypeScript
83 lines
2.6 KiB
TypeScript
import { expect, it } from "vitest";
|
|
import { readElfRelocationEntry } from "./elfRelocation.js";
|
|
|
|
const formats = [
|
|
{ bits: 32, littleEndian: false },
|
|
{ bits: 32, littleEndian: true },
|
|
{ bits: 64, littleEndian: false },
|
|
{ bits: 64, littleEndian: true },
|
|
] as const;
|
|
|
|
it.each(formats)(
|
|
"preserves standard ELF$bits REL/RELA fields (littleEndian=$littleEndian)",
|
|
({ bits, littleEndian }) => {
|
|
const wide = bits === 64;
|
|
const wordBytes = wide ? 8 : 4;
|
|
const backing = Buffer.alloc(wordBytes * 3 + 19, 0xa5);
|
|
const bytes = backing.subarray(7, 7 + wordBytes * 3);
|
|
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
const offset = wide ? 0xffffffffffffffffn : 0xffffffffn;
|
|
const symbolIndex = wide ? 0xfedcba98 : 0xabcdef;
|
|
const type = wide ? 0x89abcdef : 0x80;
|
|
const info = (BigInt(symbolIndex) << (wide ? 32n : 8n)) | BigInt(type);
|
|
const addend = wide ? -0x8000000000000000n : -0x80000000n;
|
|
if (wide) {
|
|
view.setBigUint64(0, offset, littleEndian);
|
|
view.setBigUint64(8, info, littleEndian);
|
|
view.setBigInt64(16, addend, littleEndian);
|
|
} else {
|
|
view.setUint32(0, Number(offset), littleEndian);
|
|
view.setUint32(4, Number(info), littleEndian);
|
|
view.setInt32(8, Number(addend), littleEndian);
|
|
}
|
|
const before = Buffer.from(backing);
|
|
const rel = readElfRelocationEntry(
|
|
backing.subarray(7),
|
|
bits,
|
|
littleEndian,
|
|
"rel",
|
|
);
|
|
const rela = readElfRelocationEntry(
|
|
backing.subarray(7),
|
|
bits,
|
|
littleEndian,
|
|
"rela",
|
|
);
|
|
expect(backing.equals(before)).toBe(true);
|
|
backing.fill(0);
|
|
expect(rel).toEqual({
|
|
ok: true,
|
|
value: { offset, type, symbolIndex },
|
|
});
|
|
expect(rela).toEqual({
|
|
ok: true,
|
|
value: { offset, type, symbolIndex, addend },
|
|
});
|
|
},
|
|
);
|
|
|
|
it.each(formats)(
|
|
"refuses every incomplete ELF$bits REL/RELA entry (littleEndian=$littleEndian)",
|
|
({ bits, littleEndian }) => {
|
|
const wordBytes = bits === 64 ? 8 : 4;
|
|
const bytes = Buffer.alloc(wordBytes * 3 + 7);
|
|
for (let observed = 0; observed < wordBytes * 3; observed++) {
|
|
const input = bytes.subarray(7, 7 + observed);
|
|
const failure = {
|
|
ok: false,
|
|
error: {
|
|
kind: "malformed",
|
|
message: "ELF relocation entry is truncated",
|
|
},
|
|
};
|
|
expect(readElfRelocationEntry(input, bits, littleEndian, "rela")).toEqual(
|
|
failure,
|
|
);
|
|
if (observed < wordBytes * 2)
|
|
expect(
|
|
readElfRelocationEntry(input, bits, littleEndian, "rel"),
|
|
).toEqual(failure);
|
|
}
|
|
},
|
|
);
|