Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

129 lines
5.7 KiB
TeX

\section{InstructionAPI Modules and Abstractions}
The Instruction API contains three major components: the top-\/level instruction
representation, the abstract syntax trees representing the operands of an
instruction, and the decoder that creates the entire representation. We will
present an overview of the features and uses of each of these three components,
followed by an example of how the Instruction API can be applied to binary
analysis.
\subsection{Instruction Interface}
The Instruction API represents a machine language instruction as an Instruction
object, which contains an Operation and a collection of Operands. The Operation
contains the following items:
\begin{itemize}
\item The mnemonic for the machine language instruction represented by its associated Instruction
\item The number of operands accepted by the Operation
\item Which Operands are read and/or written by the associated machine operation
\item What other registers (if any) are affected by the underlying machine operation
\end{itemize}
Each Operand contains flags to indicate whether it is read, written, or both by
the machine instruction represented by its parent Instruction, and contains a
Expression abstract syntax tree representing the operations required to compute
the value of the operand. Figure~\ref{fig:ownership-graph} depicts these
ownership relationships within an Instruction.
\begin{figure}
\centering
\includegraphics{fig/ownership_graph}
\caption{An Instruction and the objects it owns}
\label{fig:ownership-graph}
\end{figure}
Instruction objects provide two types of interfaces: direct read access to their
components, and common summary operations on those components. The first
interface allows access to the Operation and Operand data members, and each
Operand object in turn allows traversal of its abstract syntax tree. More
details about how to work with this abstract syntax tree can be found in
Section~\ref{subsec:hierarchy}.
This interface would be used, for example, in a data flow analysis where a user wants
to evaluate the results of an effective address computation given a known
register state.
The second interface allows a user to get the sets of registers read and written
by the instruction, information about how the instruction accesses memory, and
information about how the instruction affects control flow, without having to
manipulate the Operands directly. For instance, a user could implement a
register liveness analysis algorithm using just this second interface (namely
the \code{getReadSet} and \code{getWriteSet} functions).
\subsection{Instruction Decoding}
An InstructionDecoder interprets a sequence of bytes according to a given
machine language and transforms them into an instruction representation. It
determines the opcode of the machine instruction, translates that opcode to an
Operation object, uses that Operation to determine how to decode the
instruction's Operands, and produces a decoded Instruction.
\begin{figure}
\centering
\includegraphics[scale=.8]{fig/decoder_use}
\caption{The InstructionDecoder's inputs and outputs}
\label{fig:decoder-use}
\end{figure}
Instruction decoders are built from the following elements:
\begin{itemize}
\item A function to find and extract an opcode given a pointer into a buffer that points to the beginning of a machine instruction
\item A table that, for a particular architecture, maps opcodes to Operations and functions that decode Operands
\end{itemize}
From these elements, it is possible to generalize the construction of
Instructions from Operations and Operands to an entirely platform-\/independent
algorithm. Likewise, much of the construction of the ASTs representing each
operand can be performed in a platform-\/independent manner.
\subsection{InstructionAST Hierarchy}
\label{subsec:hierarchy}
The AST representation of an operand encapsulates the operations performed on
registers and immediates to produce an operand for the machine language
instruction.
The inheritance hierarchy of the AST classes is shown in
Figure~\ref{fig:inheritance}.
\begin{figure}
\centering
\includegraphics{fig/full_inheritance_graph}
\caption{The InstructionAST inheritance hierarchy}
\label{fig:inheritance}
\end{figure}
The grammar for these AST representations is simple: all leaves must be
RegisterAST or Immediate nodes. These nodes may be combined using a
BinaryFunction node, which may be constructed as either an addition or a
multiplication. Also, a single node may descend from a Dereference node, which
treats its child as a memory address. Figure~\ref{fig:ownership} shows the allowable parent/child
relationships within a given tree, and Figure~\ref{fig:representation} shows how an example IA32
instruction is represented using these objects.
\begin{figure}
\centering
\includegraphics{fig/ast_ownership}
\caption{InstructionAST intermediate node types and the objects they own}
\label{fig:ownership}
\end{figure}
\begin{figure}
\centering
\includegraphics{fig/instruction_representation}
\caption{The decomposition of \code{mov} \code{\%eax}, (\code{\%esi})}
\label{fig:representation}
\end{figure}
These ASTs may be searched for leaf elements or subtrees (via
\code{getUses} and \code{isUsed}) and traversed breadth-\/first or depth-\/first
(via \code{getChildren}).
Any node in these ASTs may be evaluated. Evaluation attempts to determine the
value represented by a node. If successful, it will return that value and cache
it in the node. The tree structure, combined with the evaluation mechanism,
allows the substitution of known register and memory values into an operand,
regardless of whether those values are known at the time an instruction is
decoded. More details on this mechanism may be found in
Section~\ref{sec:expression}.