Skip to content

Latest commit

 

History

History
107 lines (81 loc) · 5.73 KB

README.md

File metadata and controls

107 lines (81 loc) · 5.73 KB

aslp-lifter-cpp

This repository contains source files for an arm lifter, generated by aslp's offline partial evaluation.

lifter

The generated aslp_lifter is a polymorphic C++ class with a type parameter to support retargeting the lifter to emit different IR targets (e.g. LLVM IR). The methods which a backend interface must provide are declared in the lifter_interface class and further explained in the next section.

The entry point of the lifter is f_A64_decoder which decodes the given opcode and calls a lifter function for that particular encoding (e.g. f_aarch64_branch_unconditional_immediate). Within this lifter function, methods from the lifter interface are called to implement the IR generation.

interface

The lifter_interface is the interface which the generated aslp_lifter interacts with. The Traits parameter to lifter_interface defines the fundamental types which the interface operates with. By providing different implementations of the interface and its traits, the lifter can be retargeted to interpret the semantics in different ways. For example, llvm_interface represents the semantics by emitting LLVM IR, and other interfaces can be conceived to target other intermediate representations or even emulate the semantics in software.

Within the interface, there is an important distinction between two different stages of evaluation:

  • lift-time refers to the execution of the lifter's C++ code. The Traits types concerning lift-time are ::bits for fixed-length bit-vectors, and ::bigint for arbitrary-sized integers. For example, the opcode is given to the lifter functions as a ::bits value, so the opcode and anything derived from it is said to be known at lift-time. However, anything concerning machine state must be deferred to run-time via the f_gen_* methods of lifter_interface.
  • run-time refers to the interpretation of the semantics produced during lift-time (e.g. LLVM IR). Here, the important types are prefixed with rt_: ::rt_expr is the type for ordinary run-time values, ::rt_lexpr is used for run-time variables, and ::rt_label represents a run-time block. Methods which emit code for run-time begin with f_gen_.

These two stages are performed in sequence, and we must be careful not to mix up the two. For example, lift-time information is forgotten at run-time unless explicitly converted. The rt_ types are also merely a C++ convenience - they need not be distinct, and they need not precisely correspond to actual run-time types. Of course, they should satisfy the C++ type checker, but the lifter will not impose additional expectations on them.

llvm_lifter_traits and llvm_interface can be consulted for examples. The llvm_interface is divided explicitly into lift-time and run-time components.

usage of headers

The generated lifter template is fairly large. If included in its entirety, it would take a substantial amount of time and memory to compile. We alleviate this by splitting the lifter class's header into a forward declaration header, accompanied with a separate header file for each lifter function definition.

To make use of the lifter in downstream projects, including aslp_lifter is sufficient. This will need to be linked against a library providing the required symbols.

For compiling the library, we provide subprojects/aslp-lifter/src/generated which is a folder of C++ files, each instantiating a single lifter function with a particular Traits class. The traits are defined by a compiler macro, ASLP_LIFTER_INSTANTIATE, which should expand to the required Traits class name. Header files can be included with the -include compiler argument.

Examples of this can be seen in the Meson and CMake projects, described below.

usage

To integrate the lifter with other applications, you can make use of the Meson and CMake files in this repository.

In Meson (preferred), we define several subprojects:

  • aslp-lifter is the main project, containing the lifter definition in header files and source files to support explicit instantiation of the lifter template.
  • aslp-lifter-llvm uses the aslp-lifter sources to build a lifter to LLVM. It provides a library for users to link against.
  • aslp-lifter-demo builds an executable which takes a numeric (big-endian) opcode and emits its LLVM semantics. This demonstrates use of the preceding two libraries.

Meson is very easy to use. These commands will configure and build the project into a build/ subdirectory. It is suggested to use Clang, as it is much faster than GCC in our testing.

CXX=clang++ meson setup build
meson compile -C build

The CMakeLists is provided so this repository may be used with FetchContent. However, it does not make much effort to separate the subprojects, and it is not installable.

generating

At present, this repository is updated manually. The files are generated by running this command from aslp's directory. Replace $ASLP_LIFTER_CPP_DIR with this repository's directory:

echo ':gen A64 .+ cpp $ASLP_LIFTER_CPP_DIR/subprojects/aslp-lifter' | dune exec asli

When commiting to Git, make sure to add the generated subfolder changes with -f. They are ignored by default to avoid cluttering git output.