mirror of
https://github.com/morluto/rea
synced 2026-10-27 06:33:32 -04:00
@@ -21,7 +21,7 @@ const unsupported = (message: string) =>
|
||||
|
||||
interface RelocatedImage {
|
||||
readonly bytes: Buffer;
|
||||
readonly unresolved: Set<bigint>;
|
||||
readonly unresolved: Map<bigint, number>;
|
||||
readonly zeroFillPointers: Map<bigint, bigint>;
|
||||
}
|
||||
interface RelocationSource {
|
||||
@@ -29,7 +29,7 @@ interface RelocationSource {
|
||||
readonly mappings: readonly FileMapping[];
|
||||
readonly zeroFills: readonly ZeroFillMapping[];
|
||||
readonly relative: number;
|
||||
readonly unknownPointerKinds: ReadonlySet<number>;
|
||||
readonly unknownPointerWidths: ReadonlyMap<number, number>;
|
||||
}
|
||||
|
||||
/** Standard dynamic relocations whose destination spans at most eight bytes.
|
||||
@@ -41,8 +41,19 @@ const RELOCATION_KINDS = new Map([
|
||||
183,
|
||||
{
|
||||
relative: 1027,
|
||||
unknownPointerKinds: new Set([
|
||||
257, 258, 259, 260, 261, 262, 1025, 1026, 1028, 1029, 1030, 1032,
|
||||
unknownPointerWidths: new Map([
|
||||
[257, 8],
|
||||
[258, 4],
|
||||
[259, 2],
|
||||
[260, 8],
|
||||
[261, 4],
|
||||
[262, 2],
|
||||
[1025, 8],
|
||||
[1026, 8],
|
||||
[1028, 8],
|
||||
[1029, 8],
|
||||
[1030, 8],
|
||||
[1032, 8],
|
||||
]),
|
||||
},
|
||||
],
|
||||
@@ -50,7 +61,19 @@ const RELOCATION_KINDS = new Map([
|
||||
62,
|
||||
{
|
||||
relative: 8,
|
||||
unknownPointerKinds: new Set([1, 2, 6, 7, 10, 11, 16, 17, 18, 24, 37]),
|
||||
unknownPointerWidths: new Map([
|
||||
[1, 8],
|
||||
[2, 4],
|
||||
[6, 8],
|
||||
[7, 8],
|
||||
[10, 4],
|
||||
[11, 4],
|
||||
[16, 8],
|
||||
[17, 8],
|
||||
[18, 8],
|
||||
[24, 8],
|
||||
[37, 8],
|
||||
]),
|
||||
},
|
||||
],
|
||||
]);
|
||||
@@ -148,19 +171,20 @@ function* applyRelaTable(
|
||||
kind = Number(info & 0xffffffffn);
|
||||
if (kind === 0) continue;
|
||||
const destination = source.image.readBigUInt64LE(at);
|
||||
const target = fileOffset(source.mappings, destination, 8);
|
||||
if (kind !== source.relative || info >> 32n !== 0n) {
|
||||
if (!source.unknownPointerKinds.has(kind))
|
||||
const width = source.unknownPointerWidths.get(kind);
|
||||
if (width === undefined)
|
||||
throw unsupported(`ELF relocation kind ${kind} is not decoded`);
|
||||
if (!output.unresolved.has(destination)) {
|
||||
admitOverlay(output);
|
||||
output.unresolved.add(destination);
|
||||
}
|
||||
const priorWidth = output.unresolved.get(destination);
|
||||
if (priorWidth === undefined) admitOverlay(output);
|
||||
output.unresolved.set(destination, Math.max(priorWidth ?? 0, width));
|
||||
// Registration scans read this private image directly. Clear unknown
|
||||
// fields so their stored bytes cannot masquerade as resolved pointers.
|
||||
if (target !== null) output.bytes.fill(0, target, target + 8);
|
||||
const target = fileOffset(source.mappings, destination, width);
|
||||
if (target !== null) output.bytes.fill(0, target, target + width);
|
||||
continue;
|
||||
}
|
||||
const target = fileOffset(source.mappings, destination, 8);
|
||||
const value = source.image.readBigInt64LE(at + 16) & 0xffffffffffffffffn;
|
||||
if (target !== null) output.bytes.writeBigUInt64LE(value, target);
|
||||
else if (
|
||||
@@ -196,7 +220,7 @@ export function* applyElfRelativeRelocationsSteps(
|
||||
yield;
|
||||
const output: RelocatedImage = {
|
||||
bytes: Buffer.from(image),
|
||||
unresolved: new Set(),
|
||||
unresolved: new Map(),
|
||||
zeroFillPointers: new Map(),
|
||||
};
|
||||
const source = { image, mappings, zeroFills, ...kinds };
|
||||
|
||||
@@ -66,7 +66,7 @@ export interface NativeImage {
|
||||
readonly bytes: Buffer;
|
||||
readonly container: BinaryContainer;
|
||||
readonly imageBase: bigint;
|
||||
readonly unresolvedPointerSlots: ReadonlySet<bigint>;
|
||||
readonly unresolvedPointerSlots: ReadonlyMap<bigint, number>;
|
||||
readonly zeroFillPointers: ReadonlyMap<bigint, bigint>;
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ export function* openImageSteps(
|
||||
let relocated:
|
||||
| {
|
||||
bytes: Buffer;
|
||||
unresolved: ReadonlySet<bigint>;
|
||||
unresolved: ReadonlyMap<bigint, number>;
|
||||
zeroFillPointers: ReadonlyMap<bigint, bigint>;
|
||||
}
|
||||
| undefined;
|
||||
@@ -151,7 +151,7 @@ export function* openImageSteps(
|
||||
bytes: image,
|
||||
container,
|
||||
imageBase,
|
||||
unresolvedPointerSlots: relocated?.unresolved ?? new Set<bigint>(),
|
||||
unresolvedPointerSlots: relocated?.unresolved ?? new Map<bigint, number>(),
|
||||
zeroFillPointers: relocated?.zeroFillPointers ?? new Map<bigint, bigint>(),
|
||||
};
|
||||
}
|
||||
@@ -295,10 +295,10 @@ const hasUnresolvedPointer = (
|
||||
size = 8,
|
||||
): boolean => {
|
||||
if (image.unresolvedPointerSlots.size === 0) return false;
|
||||
// Unsupported relocation widths are unknown; conservatively cover any
|
||||
// overlap with the pointer rather than infer a zero or trust stored bytes.
|
||||
for (let delta = -7; delta < size; delta++)
|
||||
if (image.unresolvedPointerSlots.has(address + BigInt(delta))) return true;
|
||||
for (let delta = -7; delta < size; delta++) {
|
||||
const width = image.unresolvedPointerSlots.get(address + BigInt(delta));
|
||||
if (width !== undefined && delta + width > 0) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user