mirror of
https://github.com/morluto/rea.git
synced 2026-10-29 10:55:57 +00:00
* feat(ghidra): admit 32-bit big-endian PowerPC ELF Recognize EM_PPC as a provider-neutral `powerpc` family that keeps its ELF class, byte order, type and flags, and admit ELF32 big-endian ET_EXEC through a bounded Ghidra lane. ELF64, little-endian, relocatable/shared objects and EF_PPC_EMB are refused with a specific reason; Hopper and IDA do not gain PowerPC support, and Windows Ghidra P0 is unchanged. Ghidra's ELF loader selects PowerPC:BE:32:e500:default for a plain EM_PPC header, which misreads 750-family code. The lane binds PowerPC:BE:32:default/default in the profile (language_selection "admitted-lane-v1"), imports with it and checks the reported language. A language set through REA_GHIDRA_LANGUAGE_ID still replaces the lane default. Add a source-owned fixture, fixed-encoding probe, GNU readelf cross-check and the optional `verify:ghidra:ppc` real-provider lane, plus docs/ghidra-ppc.md. Refs #1741 * style(ghidra): format shared PowerPC profile integration * fix(ghidra): preserve caller-selected PowerPC languages --------- Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
59 lines
1.9 KiB
TypeScript
59 lines
1.9 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { parseExecutableHeader } from "./binaryTarget.js";
|
|
|
|
const header = (little: boolean, bits: 32 | 64 = 32, machine = 20): Buffer => {
|
|
const bytes = Buffer.alloc(bits === 32 ? 52 : 64);
|
|
bytes.set([0x7f, 0x45, 0x4c, 0x46, bits === 32 ? 1 : 2, little ? 1 : 2, 1]);
|
|
if (little) {
|
|
bytes.writeUInt16LE(2, 16);
|
|
bytes.writeUInt16LE(machine, 18);
|
|
bytes.writeUInt32LE(1, 20);
|
|
bytes.writeUInt16LE(bytes.length, bits === 32 ? 40 : 52);
|
|
} else {
|
|
bytes.writeUInt16BE(2, 16);
|
|
bytes.writeUInt16BE(machine, 18);
|
|
bytes.writeUInt32BE(1, 20);
|
|
bytes.writeUInt16BE(bytes.length, bits === 32 ? 40 : 52);
|
|
}
|
|
return bytes;
|
|
};
|
|
|
|
describe("PowerPC ELF header boundaries", () => {
|
|
it.each([false, true])(
|
|
"retains source endian and flags (little=%s)",
|
|
(little) => {
|
|
const parsed = parseExecutableHeader(header(little), "x64");
|
|
if (!parsed.ok) throw new Error(parsed.error);
|
|
expect(parsed.value).toEqual({
|
|
format: "elf",
|
|
architecture: "powerpc",
|
|
availableArchitectures: ["powerpc"],
|
|
powerpc: {
|
|
elfClass: 32,
|
|
byteOrder: little ? "little" : "big",
|
|
type: 2,
|
|
flags: 0,
|
|
},
|
|
});
|
|
},
|
|
);
|
|
|
|
it("reads ELF64 flags at their own offset without claiming support", () => {
|
|
const bytes = header(false, 64);
|
|
bytes.writeUInt32BE(0x80000000, 48);
|
|
const parsed = parseExecutableHeader(bytes, "x64");
|
|
if (!parsed.ok) throw new Error(parsed.error);
|
|
expect(parsed.value).toMatchObject({
|
|
architecture: "powerpc",
|
|
powerpc: { elfClass: 64, byteOrder: "big", flags: 0x80000000 },
|
|
});
|
|
});
|
|
|
|
it("does not recognize EM_PPC64 as the 32-bit family", () => {
|
|
expect(parseExecutableHeader(header(false, 64, 21), "x64")).toEqual({
|
|
ok: false,
|
|
error: "unsupported ELF architecture",
|
|
});
|
|
});
|
|
});
|