Skip to content

Commit

Permalink
tracer: Integrate with browser's navigation state
Browse files Browse the repository at this point in the history
To be able to go back/forward when exploring code and data.
  • Loading branch information
oleavr committed Oct 6, 2024
1 parent cdc13cc commit 2ed4128
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 47 deletions.
40 changes: 18 additions & 22 deletions apps/tracer/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import "./App.css";
import AddTargetsDialog from "./AddTargetsDialog.tsx";
import DisassemblyView, { type DisassemblyTarget } from "./DisassemblyView.tsx";
import DisassemblyView from "./DisassemblyView.tsx";
import EventView from "./EventView.tsx";
import HandlerEditor from "./HandlerEditor.tsx";
import HandlerList from "./HandlerList.tsx";
Expand All @@ -15,7 +15,7 @@ import {
Tabs,
Tab,
} from "@blueprintjs/core";
import { useRef, useState } from "react";
import { useRef } from "react";
import { Resplit } from "react-resplit";

export default function App() {
Expand All @@ -37,11 +37,20 @@ export default function App() {
captureBacktraces,
setCaptureBacktraces,

selectedTabId,
setSelectedTabId,

events,
latestMatchingEventIndex,
selectedEventIndex,
setSelectedEventIndex,

disassemblyTarget,
disassemble,

memoryLocation,
showMemoryLocation,

addingTargets,
startAddingTargets,
finishAddingTargets,
Expand All @@ -54,9 +63,6 @@ export default function App() {
symbolicate,
} = useModel();
const captureBacktracesSwitchRef = useRef<HTMLInputElement>(null);
const [selectedTabId, setSelectedTabId] = useState("events");
const [disassemblyTarget, setDisassemblyTarget] = useState<DisassemblyTarget>();
const [memoryLocation, setMemoryLocation] = useState<bigint | undefined>();

const connectionError = lostConnection
? <Callout
Expand All @@ -76,10 +82,7 @@ export default function App() {
onDeactivate={() => {
setSelectedEventIndex(null);
}}
onDisassemble={address => {
setSelectedTabId("disassembly");
setDisassemblyTarget({ type: "instruction", address });
}}
onDisassemble={disassemble}
onSymbolicate={symbolicate}
/>
);
Expand All @@ -88,12 +91,9 @@ export default function App() {
<DisassemblyView
target={disassemblyTarget}
handlers={handlers}
onSelectTarget={setDisassemblyTarget}
onSelectTarget={disassemble}
onSelectHandler={setSelectedHandlerId}
onSelectMemoryLocation={address => {
setSelectedTabId("memory");
setMemoryLocation(address);
}}
onSelectMemoryLocation={showMemoryLocation}
onAddInstructionHook={addInstructionHook}
onSymbolicate={symbolicate}
/>
Expand All @@ -116,7 +116,7 @@ export default function App() {
onHandlerSelect={setSelectedHandlerId}
/>
<ButtonGroup className="target-actions" vertical={true} minimal={true} alignText="left">
<Button intent="success" icon="add" onClick={startAddingTargets}>Add</Button>
<Button intent="success" icon="add" onClick={startAddingTargets}>Add</Button>
{(spawnedProgram !== null) ? <Button intent="danger" icon="reset" onClick={respawn}>Respawn</Button> : null}
</ButtonGroup>
</section>
Expand All @@ -134,19 +134,15 @@ export default function App() {
<Button
icon="arrow-down"
disabled={latestMatchingEventIndex === null}
onClick={() => {
setSelectedTabId("events");
setSelectedEventIndex(latestMatchingEventIndex);
}}
onClick={() => setSelectedEventIndex(latestMatchingEventIndex)}
>
Latest Event
</Button>
<Button
icon="code"
disabled={lostConnection || selectedHandler === null || selectedHandler.address === null}
onClick={() => {
setSelectedTabId("disassembly");
setDisassemblyTarget({
disassemble({
type: (selectedHandler!.flavor === "insn") ? "instruction" : "function",
name: selectedHandler!.display_name,
address: BigInt(selectedHandler!.address!)
Expand Down Expand Up @@ -174,7 +170,7 @@ export default function App() {
</Resplit.Pane>
<Resplit.Splitter className="app-splitter" order={1} size="5px" />
<Resplit.Pane className="bottom-area" order={2} initialSize="0.5fr">
<Tabs className="bottom-tabs" selectedTabId={selectedTabId} onChange={tabId => setSelectedTabId(tabId as string)} animate={false}>
<Tabs className="bottom-tabs" selectedTabId={selectedTabId} onChange={tabId => setSelectedTabId(tabId as any)} animate={false}>
<Tab id="events" title="Events" panel={eventView} panelClassName="bottom-tab-panel" />
<Tab id="disassembly" title="Disassembly" panel={disassemblyView} panelClassName="bottom-tab-panel" />
<Tab id="memory" title="Memory" panel={memoryView} panelClassName="bottom-tab-panel" />
Expand Down
15 changes: 1 addition & 14 deletions apps/tracer/src/DisassemblyView.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import "./DisassemblyView.css";
import { Handler, HandlerId } from "./model.js";
import { DisassemblyTarget, Handler, HandlerId } from "./model.js";
import { useR2 } from "@frida/react-use-r2";
import { hideContextMenu, Menu, MenuItem, showContextMenu, Spinner } from "@blueprintjs/core";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
Expand All @@ -14,19 +14,6 @@ export interface DisassemblyViewProps {
onSymbolicate: SymbolicateRequestHandler;
}

export type DisassemblyTarget = FunctionTarget | InstructionTarget;

export interface FunctionTarget {
type: "function";
name?: string;
address: bigint;
}

export interface InstructionTarget {
type: "instruction";
address: bigint;
}

export type SelectTargetRequestHandler = (target: DisassemblyTarget) => void;
export type SelectHandlerRequestHandler = (id: HandlerId) => void;
export type SelectMemoryLocationRequestHandler = (address: bigint) => void;
Expand Down
16 changes: 10 additions & 6 deletions apps/tracer/src/EventView.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import "./EventView.css";
import { Event, HandlerId } from "./model.js";
import { DisassemblyTarget, Event, HandlerId } from "./model.js";
import { Button, Card } from "@blueprintjs/core";
import { ReactElement, useEffect, useRef, useState } from "react";
import { ReactElement, useCallback, useEffect, useRef, useState } from "react";
import { useStayAtBottom } from "react-stay-at-bottom";

export interface EventViewProps {
Expand All @@ -14,7 +14,7 @@ export interface EventViewProps {
}

export type EventActionHandler = (handlerId: HandlerId, eventIndex: number) => void;
export type DisassembleHandler = (address: bigint) => void;
export type DisassembleHandler = (target: DisassemblyTarget) => void;
export type SymbolicateHandler = (addresses: bigint[]) => Promise<string[]>;

const NON_BLOCKING_SPACE = "\u00A0";
Expand Down Expand Up @@ -86,7 +86,11 @@ export default function EventView({
return () => {
ignore = true;
};
}, [events, selectedIndex, onSymbolicate])
}, [events, selectedIndex, onSymbolicate]);

const handleDisassemblyRequest = useCallback((rawAddress: string) => {
onDisassemble({ type: "instruction", address: BigInt(rawAddress) });
}, [onDisassemble]);

let selectedEventDetails: ReactElement | undefined;
if (selectedIndex !== null) {
Expand All @@ -106,7 +110,7 @@ export default function EventView({
<tr>
<td>Caller</td>
<td>
<Button onClick={() => onDisassemble(BigInt(caller))}>{selectedCallerSymbol ?? caller}</Button>
<Button onClick={() => handleDisassemblyRequest(caller)}>{selectedCallerSymbol ?? caller}</Button>
</td>
</tr>
) : null
Expand All @@ -116,7 +120,7 @@ export default function EventView({
<td>Backtrace</td>
<td>
{backtrace.map((address, i) =>
<Button key={address} alignText="left" onClick={() => onDisassemble(BigInt(address))}>
<Button key={address} alignText="left" onClick={() => handleDisassemblyRequest(address)}>
{(selectedBacktraceSymbols !== null) ? selectedBacktraceSymbols[i] : address}
</Button>)}
</td>
Expand Down
Loading

0 comments on commit 2ed4128

Please sign in to comment.