diff --git a/apps/tracer/src/App.tsx b/apps/tracer/src/App.tsx index 2558937..bbbddb2 100644 --- a/apps/tracer/src/App.tsx +++ b/apps/tracer/src/App.tsx @@ -100,7 +100,10 @@ export default function App() { ); const memoryView = ( - + ); return ( diff --git a/apps/tracer/src/MemoryView.css b/apps/tracer/src/MemoryView.css index 979571c..b7e46a0 100644 --- a/apps/tracer/src/MemoryView.css +++ b/apps/tracer/src/MemoryView.css @@ -1,5 +1,4 @@ .memory-view { - padding: 5px; overflow: auto; font-family: monospace; font-size: 10px; @@ -8,12 +7,25 @@ user-select: text; } +.memory-view-toolbar { + display: flex; + background-color: white; + padding: 5px 7px; + border: 1px solid; +} + +.memory-view-data { + padding: 5px 7px; +} + +.memory-view .bp5-control-group .bp5-input { + font-size: 12px; +} + .memory-view .bp5-segmented-control { - position: absolute; - bottom: 5px; - right: 5px; + margin-left: 20px; } .memory-view .bp5-segmented-control .bp5-button { - font-size: 10px; + font-size: 12px; } diff --git a/apps/tracer/src/MemoryView.tsx b/apps/tracer/src/MemoryView.tsx index e7c2ecb..bd444d2 100644 --- a/apps/tracer/src/MemoryView.tsx +++ b/apps/tracer/src/MemoryView.tsx @@ -1,13 +1,17 @@ import "./MemoryView.css"; -import { SegmentedControl, Spinner } from "@blueprintjs/core"; +import { Button, ControlGroup, InputGroup, SegmentedControl, Spinner } from "@blueprintjs/core"; import { useR2 } from "@frida/react-use-r2"; -import { useEffect, useState } from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; export interface MemoryViewProps { address?: bigint; + onSelectAddress: SelectAddressHandler; } -export default function MemoryView({ address }: MemoryViewProps) { +export type SelectAddressHandler = (address: bigint) => void; + +export default function MemoryView({ address, onSelectAddress }: MemoryViewProps) { + const addressInputRef = useRef(null); const [format, setFormat] = useState("x"); const [data, setData] = useState(""); const [isLoading, setIsLoading] = useState(false); @@ -38,6 +42,19 @@ export default function MemoryView({ address }: MemoryViewProps) { }; }, [format, address, executeR2Command]); + useEffect(() => { + if (address === undefined) { + return; + } + + addressInputRef.current!.value = `0x${address.toString(16)}`; + }, [address]); + + const adjustAddress = useCallback((delta: number) => { + const newAddress = BigInt(addressInputRef.current!.value) + BigInt(delta); + onSelectAddress(newAddress); + }, [onSelectAddress]); + if (isLoading) { return ( @@ -46,26 +63,42 @@ export default function MemoryView({ address }: MemoryViewProps) { return ( - - + + + adjustAddress(-16)}> + { + if (e.key === "Enter") { + e.preventDefault(); + onSelectAddress(BigInt(addressInputRef.current!.value)); + } + }} + placeholder="Memory address…" + /> + adjustAddress(16)}> + + + + ); }