make backtrace view fancy

This commit is contained in:
Corwin 2024-04-18 19:10:53 +01:00
parent 55394640b0
commit 0d4005f163
No known key found for this signature in database

View file

@ -46,19 +46,39 @@ export function BacktracePage() {
);
}
const BacktraceListWrapper = styled.div`
font-size: 1rem;
position: relative;
width: calc(100vw - 20px);
margin-left: calc(-1 * (100vw - 20px) / 2);
left: 50%;
`;
const BacktraceList = styled.ol`
overflow-x: scroll;
white-space: nowrap;
`;
function Backtrace() {
const backtrace = useClientValue(getBacktrace) ?? "";
const backtraceAddresses = useBacktraceData(backtrace);
const [files, setFile] = useState<File[]>([]);
const backtraceAddressesList =
typeof backtraceAddresses === "object" ? backtraceAddresses : [];
const backtraceError =
typeof backtraceAddresses === "string" ? backtraceAddresses : undefined;
const backtraceLocations = useBacktraceLocations(
backtraceAddresses ?? [],
backtraceAddressesList,
files ?? []
);
return (
<details>
<summary>Addresses in the backtrace</summary>
<label>
Elf file or GBA file with debug information:
<input
type="file"
onChange={(evt) => {
@ -67,31 +87,80 @@ function Backtrace() {
setFile(filesArr);
}}
/>
<ol>
{backtraceAddresses &&
backtraceAddresses.map((x, idx) => (
</label>
<BacktraceListWrapper>
<BacktraceList>
{backtraceError}
{backtraceAddressesList.map((x, idx) => (
<li key={x}>
<code>0x{x.toString(16).padStart(8, "0")}</code>
{backtraceLocations[idx] ? (
<BacktraceAddressInfo info={backtraceLocations[idx]} />
) : (
<code>0x{x.toString(16).padStart(8, "0")}</code>
)}
</li>
))}
</ol>
</BacktraceList>
</BacktraceListWrapper>
</details>
);
}
function makeNicePath(path: string) {
const srcIndex = path.lastIndexOf("/src/");
if (srcIndex < 0) return path;
const crateNameStartIndex = path.slice(0, srcIndex).lastIndexOf("/");
const crateName =
crateNameStartIndex < 0
? "<crate>"
: path.slice(crateNameStartIndex + 1, srcIndex);
return `<${crateName}>/${path.slice(srcIndex + 5)}`;
}
const GreenSpan = styled.span`
color: green;
`;
const BacktraceAddressLine = styled.ul`
list-style-type: none;
padding-left: 20px;
`;
function BacktraceAddressInfo({ info }: { info: AddressInfo[] | undefined }) {
if (!info) return;
function FunctionName({
interesting,
functionName,
}: {
interesting: boolean;
functionName: string;
}) {
if (interesting) {
return <strong>{functionName}</strong>;
}
return functionName;
}
return (
<ol>
<BacktraceAddressLine>
{info.map((x, idx) => (
<li key={idx}>
{x.is_inline && "(inlined into)"} {x.function_name}:{x.column}{" "}
{x.filename}:{x.line_number}
<code>
{x.is_inline && "(inlined into)"}{" "}
<FunctionName
interesting={x.is_interesting}
functionName={x.function_name}
/>{" "}
<GreenSpan>
{makeNicePath(x.filename)}:{x.line_number}:{x.column}
</GreenSpan>
</code>
</li>
))}
</ol>
</BacktraceAddressLine>
);
}
@ -100,17 +169,17 @@ function useBacktraceLocations(addresses: number[], file: File[]) {
const [debugInfo, setDebugInfo] = useState<AddressInfo[][]>([]);
useEffect(() => {
(async () => {
const f = file[0];
if (!f) return;
if (!debug) return;
(async () => {
const buf = await f.arrayBuffer();
const view = new Uint8Array(buf);
const agbDebugFile = debug.debug_file(view);
const debugInfo = addresses.map((x) => agbDebugFile.address_info(x));
setDebugInfo(debugInfo);
})();
return debugInfo;
})().then((x) => setDebugInfo(x ?? []));
}, [addresses, debug, file]);
return debugInfo;
@ -124,7 +193,9 @@ function useBacktraceData(trace?: string) {
if (!trace) return;
const addresses = debug?.decode_backtrace(trace);
return addresses && Array.from(addresses);
} catch {}
} catch (e: unknown) {
return `${e}`;
}
}, [debug, trace]);
}