mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 00:01:34 +11:00
make backtrace view fancy
This commit is contained in:
parent
55394640b0
commit
0d4005f163
|
@ -46,52 +46,121 @@ 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>
|
||||
<input
|
||||
type="file"
|
||||
onChange={(evt) => {
|
||||
const files = evt.target.files;
|
||||
const filesArr = (files && Array.from(files)) ?? [];
|
||||
setFile(filesArr);
|
||||
}}
|
||||
/>
|
||||
<ol>
|
||||
{backtraceAddresses &&
|
||||
backtraceAddresses.map((x, idx) => (
|
||||
<label>
|
||||
Elf file or GBA file with debug information:
|
||||
<input
|
||||
type="file"
|
||||
onChange={(evt) => {
|
||||
const files = evt.target.files;
|
||||
const filesArr = (files && Array.from(files)) ?? [];
|
||||
setFile(filesArr);
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
<BacktraceListWrapper>
|
||||
<BacktraceList>
|
||||
{backtraceError}
|
||||
{backtraceAddressesList.map((x, idx) => (
|
||||
<li key={x}>
|
||||
<code>0x{x.toString(16).padStart(8, "0")}</code>
|
||||
<BacktraceAddressInfo info={backtraceLocations[idx]} />
|
||||
{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(() => {
|
||||
const f = file[0];
|
||||
if (!f) return;
|
||||
if (!debug) return;
|
||||
(async () => {
|
||||
const f = file[0];
|
||||
if (!f) return;
|
||||
if (!debug) return;
|
||||
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]);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue