mirror of
https://github.com/morluto/rea
synced 2026-10-25 14:01:13 -04:00
fix(apple): keep the nested Rosetta registers of translated crash reports
A translated process records Rosetta's registers in a nested threadState.rosetta object. The parser read it as one register, so every valid report from a Rosetta process came back partial with a threadState.rosetta.value mismatch, and the nested registers were dropped. Each nested member is now reported as rosetta.<name> and counts toward the register budget.
This commit is contained in:
@@ -38,6 +38,9 @@ address uses that row's own image base and offset. The recorded `inline` flag
|
||||
does not supply a missing offset or authorize borrowing another row's address.
|
||||
When `faultingThread` is missing or does not resolve to a recorded thread
|
||||
object, row-zero roles are `unknown`; the recorded lookup remains available.
|
||||
A translated process records Rosetta's registers in a nested
|
||||
`threadState.rosetta` object; each one is reported as `rosetta.<name>` and
|
||||
counts toward the register budget.
|
||||
`process.os_version` keeps the producer's dictionary (`train`, `build`,
|
||||
`release_type`, `is_embedded`) or the older string form. Image UUIDs are uppercase 8-4-4-4-12; an all-zero UUID
|
||||
or a missing `arch` is `uuid_unknown`. Image `source` letters keep their
|
||||
|
||||
@@ -96,6 +96,13 @@ const threadShape = (
|
||||
members: {
|
||||
flavor: SCALAR,
|
||||
x: { kind: "array", items: register, beforeItem: take.registers },
|
||||
// Rosetta-translated processes nest their translator registers.
|
||||
rosetta: {
|
||||
kind: "object",
|
||||
members: {},
|
||||
rest: register,
|
||||
beforeRest: take.registers,
|
||||
},
|
||||
},
|
||||
rest: register,
|
||||
beforeRest: take.registers,
|
||||
|
||||
@@ -500,6 +500,46 @@ it("reports wrong-type collections as partial instead of empty and complete", ()
|
||||
expect(empty.coverage.status).toBe("complete");
|
||||
});
|
||||
|
||||
it("keeps the nested Rosetta registers of a translated process", () => {
|
||||
const parsed = parse(
|
||||
withBody(`{
|
||||
"translated": true,
|
||||
"threads": [
|
||||
{
|
||||
"threadState": {
|
||||
"flavor": "x86_THREAD_STATE",
|
||||
"rip": { "value": 4294983680 },
|
||||
"rosetta": { "tmp0": { "value": 7 }, "tmp1": 8 }
|
||||
}
|
||||
}
|
||||
],
|
||||
"usedImages": []
|
||||
}`),
|
||||
);
|
||||
expect(parsed.threads[0]?.registers).toEqual([
|
||||
{
|
||||
name: "rip",
|
||||
value: { decimal: "4294983680", hex: "0x100004000" },
|
||||
description: null,
|
||||
},
|
||||
{
|
||||
name: "rosetta.tmp0",
|
||||
value: { decimal: "7", hex: "0x7" },
|
||||
description: null,
|
||||
},
|
||||
{
|
||||
name: "rosetta.tmp1",
|
||||
value: { decimal: "8", hex: "0x8" },
|
||||
description: null,
|
||||
},
|
||||
]);
|
||||
expect(parsed.coverage).toMatchObject({
|
||||
status: "complete",
|
||||
registers: 3,
|
||||
type_mismatches: [],
|
||||
});
|
||||
});
|
||||
|
||||
it("records wrong-type rows, scalars and registers with their source path", () => {
|
||||
const parsed = parse(
|
||||
withBody(`{
|
||||
@@ -511,7 +551,7 @@ it("records wrong-type rows, scalars and registers with their source path", () =
|
||||
7,
|
||||
{
|
||||
"frames": [{ "imageIndex": 99999999999, "imageOffset": "8" }, []],
|
||||
"threadState": { "flavor": 1, "x": [1, "two", { "value": null }, {}], "rosetta": { "tmp0": 1 } }
|
||||
"threadState": { "flavor": 1, "x": [1, "two", { "value": null }, {}], "rosetta": { "tmp0": "one" } }
|
||||
}
|
||||
],
|
||||
"usedImages": [null, { "base": 1.0 }]
|
||||
@@ -567,9 +607,9 @@ it("records wrong-type rows, scalars and registers with their source path", () =
|
||||
observed: "absent",
|
||||
},
|
||||
{
|
||||
path: "body.threads[1].threadState.rosetta.value",
|
||||
expected: "integer",
|
||||
observed: "absent",
|
||||
path: "body.threads[1].threadState.rosetta.tmp0",
|
||||
expected: "integer or object with integer value",
|
||||
observed: "string",
|
||||
},
|
||||
{
|
||||
path: "body.threads[1].threadState.flavor",
|
||||
|
||||
@@ -175,6 +175,20 @@ const threadStateOf = (
|
||||
});
|
||||
for (const [key, entry] of Object.entries(members)) {
|
||||
if (key === "x" || key === "flavor") continue;
|
||||
if (key === "rosetta") {
|
||||
// A translated process records Rosetta's registers as a nested state.
|
||||
const rosetta = read.object(entry, `${path}.rosetta`);
|
||||
for (const [name, nested] of Object.entries(rosetta?.members ?? {})) {
|
||||
const register = registerValue(
|
||||
`rosetta.${name}`,
|
||||
nested,
|
||||
`${path}.rosetta.${name}`,
|
||||
read,
|
||||
);
|
||||
if (register !== null) registers.push(register);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const register = registerValue(key, entry, `${path}.${key}`, read);
|
||||
if (register !== null) registers.push(register);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user