Skip to content

Commit

Permalink
Allow all LLVM versions >= 15 and support dynamic linking (#55)
Browse files Browse the repository at this point in the history
* Use newest llvm-sys build.rs and support dyn linking

* Bump LLVM to version 18

Use LLVM version 18 in all build scripts, since it is fully compatible
with the existing LLVM 15 code.

* Allow llvm version >= 15

* Bump CI checkout to use v4

* Set supported versions to 15-18
  • Loading branch information
stuxnot authored Nov 13, 2024
1 parent f0ee670 commit e0fa780
Show file tree
Hide file tree
Showing 10 changed files with 503 additions and 178 deletions.
104 changes: 97 additions & 7 deletions .github/workflows/cpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,119 @@ on:

env:
CARGO_TERM_COLOR: always
NYXSTONE_LLVM_PREFIX: "/usr/lib/llvm-15/"

jobs:
linux:
linux-llvm-15:
runs-on: ubuntu-latest
env:
NYXSTONE_LLVM_PREFIX: "/usr/lib/llvm-15/"
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Packages
run: sudo apt-get install llvm-15 llvm-15-dev zlib1g-dev libzstd-dev libboost-program-options-dev cppcheck clang-tidy clang-format
run: |
sudo apt-get update
sudo apt-get install zlib1g-dev libzstd-dev cppcheck clang-tidy clang-format llvm-15 llvm-15-dev
- name: Code quality - fmt
run: ./tool/format.sh check
run: ./tool/format.sh check
- name: Code quality - cppcheck
run: ./tool/static-analysis-cppcheck.sh
- name: Code quality - clang-tidy
run: ./tool/static-analysis-tidy.sh
- name: Build
run: mkdir build/ && cd build && cmake .. && make
run: |
mkdir build
cd build
cmake ..
make
- name: Test
working-directory: build/
run: make test
- name: cli
working-directory: build/
run: |
./nyxstone "mov rax, rbx"
./nyxstone "jmp label" --labels "label=0x1000"
mac-llvm-15:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Packages
run: brew install llvm@15
- name: Build
run: |
mkdir build
cd build
NYXSTONE_LLVM_PREFIX="$(brew --prefix llvm@15)" cmake ..
make
- name: Test
working-directory: build/
run: make test
- name: cli
working-directory: build/
run: |
./nyxstone "mov rax, rbx" &&
./nyxstone "mov rax, rbx"
./nyxstone "jmp label" --labels "label=0x1000"
mac-llvm-16:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Packages
run: brew install llvm@16
- name: Build
run: |
mkdir build
cd build
NYXSTONE_LLVM_PREFIX="$(brew --prefix llvm@16)" cmake ..
make
- name: Test
working-directory: build/
run: make test
- name: cli
working-directory: build/
run: |
./nyxstone "mov rax, rbx"
./nyxstone "jmp label" --labels "label=0x1000"
mac-llvm-17:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Packages
run: brew install llvm@17
- name: Build
run: |
mkdir build
cd build
NYXSTONE_LLVM_PREFIX="$(brew --prefix llvm@17)" cmake ..
make
- name: Test
working-directory: build/
run: make test
- name: cli
working-directory: build/
run: |
./nyxstone "mov rax, rbx"
./nyxstone "jmp label" --labels "label=0x1000"
mac-llvm-18:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Packages
run: brew install llvm@18
- name: Build
run: |
mkdir build
cd build
NYXSTONE_LLVM_PREFIX="$(brew --prefix llvm@18)" cmake ..
make
- name: Test
working-directory: build/
run: make test
- name: cli
working-directory: build/
run: |
./nyxstone "mov rax, rbx"
./nyxstone "jmp label" --labels "label=0x1000"
10 changes: 5 additions & 5 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ on:
pull_request:
branches: [ "main" ]

env:
NYXSTONE_LLVM_PREFIX: "/usr/lib/llvm-15/"

jobs:
build:
runs-on: ubuntu-latest
env:
working-dir: ./bindings/python
NYXSTONE_LLVM_PREFIX: "/usr/lib/llvm-15/"

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Packages
run: sudo apt-get install llvm-15 llvm-15-dev zlib1g-dev libzstd-dev
run: |
sudo apt-get update
sudo apt-get install zlib1g-dev libzstd-dev llvm-15 llvm-15-dev
- name: Build
run: pip install .
working-directory: ${{ env.working-dir }}
Expand Down
70 changes: 61 additions & 9 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,24 @@ on:

env:
CARGO_TERM_COLOR: always
NYXSTONE_LLVM_PREFIX: "/usr/lib/llvm-15/"

jobs:
linux:
linux-llvm-15:
runs-on: ubuntu-latest
env:
working-dir: ./bindings/rust
NYXSTONE_LLVM_PREFIX: "/usr/lib/llvm-15/"
NYXSTONE_LINK_FFI: "1"
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Packages
run: sudo apt-get install llvm-15 llvm-15-dev zlib1g-dev libzstd-dev
run: |
sudo apt-get update
sudo apt-get install llvm-15 llvm-15-dev zlib1g-dev libzstd-dev
- name: Code quality
run: cargo fmt --all -- --check && cargo clippy -- -D warnings
run: |
cargo fmt --all -- --check
cargo clippy -- -D warnings
working-directory: ${{ env.working-dir }}
- name: Build
run: cargo build
Expand All @@ -29,16 +34,63 @@ jobs:
run: cargo test
working-directory: ${{ env.working-dir }}

mac:
mac-llvm-15:
runs-on: macos-latest
env:
working-dir: ./bindings/rust
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Packages
run: brew install llvm@15
- name: Build
run: RUSTFLAGS="-L$(brew --prefix zstd)/lib" NYXSTONE_LLVM_PREFIX="$(brew --prefix llvm@15)" NYXSTONE_LINK_FFI=1 cargo build
working-directory: ${{ env.working-dir }}
- name: Run tests
run: RUSTFLAGS="-L$(brew --prefix zstd)/lib" RUSTDOCFLAGS="-L$(brew --prefix zstd)/lib" NYXSTONE_LLVM_PREFIX="$(brew --prefix llvm@15)" NYXSTONE_LINK_FFI=1 cargo test
working-directory: ${{ env.working-dir }}

mac-llvm-16:
runs-on: macos-latest
env:
working-dir: ./bindings/rust
steps:
- uses: actions/checkout@v4
- name: Packages
run: brew install llvm@16
- name: Build
run: RUSTFLAGS="-L$(brew --prefix zstd)/lib" NYXSTONE_LLVM_PREFIX="$(brew --prefix llvm@16)" NYXSTONE_LINK_FFI=1 cargo build
working-directory: ${{ env.working-dir }}
- name: Run tests
run: RUSTFLAGS="-L$(brew --prefix zstd)/lib" RUSTDOCFLAGS="-L$(brew --prefix zstd)/lib" NYXSTONE_LLVM_PREFIX="$(brew --prefix llvm@16)" NYXSTONE_LINK_FFI=1 cargo test
working-directory: ${{ env.working-dir }}

mac-llvm-17:
runs-on: macos-latest
env:
working-dir: ./bindings/rust
steps:
- uses: actions/checkout@v4
- name: Packages
run: brew install llvm@17
- name: Build
run: RUSTFLAGS="-L$(brew --prefix zstd)/lib" NYXSTONE_LLVM_PREFIX="$(brew --prefix llvm@17)" NYXSTONE_LINK_FFI=1 cargo build
working-directory: ${{ env.working-dir }}
- name: Run tests
run: RUSTFLAGS="-L$(brew --prefix zstd)/lib" RUSTDOCFLAGS="-L$(brew --prefix zstd)/lib" NYXSTONE_LLVM_PREFIX="$(brew --prefix llvm@17)" NYXSTONE_LINK_FFI=1 cargo test
working-directory: ${{ env.working-dir }}

mac-llvm-18:
runs-on: macos-latest
env:
working-dir: ./bindings/rust
steps:
- uses: actions/checkout@v4
- name: Packages
run: brew install llvm@18
- name: Build
run: RUSTFLAGS="-L$(brew --prefix zstd)/lib" NYXSTONE_LLVM_PREFIX=$(brew --prefix llvm@15) cargo build
run: RUSTFLAGS="-L$(brew --prefix zstd)/lib" NYXSTONE_LLVM_PREFIX="$(brew --prefix llvm@18)" NYXSTONE_LINK_FFI=1 cargo build
working-directory: ${{ env.working-dir }}
- name: Run tests
run: RUSTFLAGS="-L$(brew --prefix zstd)/lib" RUSTDOCFLAGS="-L$(brew --prefix zstd)/lib" NYXSTONE_LLVM_PREFIX=$(brew --prefix llvm@15) cargo test
run: RUSTFLAGS="-L$(brew --prefix zstd)/lib" RUSTDOCFLAGS="-L$(brew --prefix zstd)/lib" NYXSTONE_LLVM_PREFIX="$(brew --prefix llvm@18)" NYXSTONE_LINK_FFI=1 cargo test
working-directory: ${{ env.working-dir }}

4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ option(NYXSTONE_SANITIZERS "Enable sanitizers" OFF)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

if(DEFINED $ENV{NYXSTONE_LLVM_PREFIX})
if(DEFINED ENV{NYXSTONE_LLVM_PREFIX})
# Ignore LLVM_ROOT variables
set(CMAKE_FIND_USE_PACKAGE_ROOT_PATH OFF)
set(CMAKE_PREFIX_PATH $ENV{NYXSTONE_LLVM_PREFIX})
endif()

find_package(LLVM-Wrapper 15 REQUIRED COMPONENTS
find_package(LLVM-Wrapper COMPONENTS
core
mc
AllTargetsCodeGens
Expand Down
38 changes: 25 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Nyxstone is a powerful assembly and disassembly library based on LLVM. It doesn

## Core Features

* Assembles and disassembles code for all architectures supported by LLVM 15, including x86, ARM, MIPS, RISC-V and others.
* Assembles and disassembles code for all architectures supported by the linked LLVM, including x86, ARM, MIPS, RISC-V and others.

* C++ library based on LLVM with Rust and Python bindings.

Expand All @@ -51,38 +51,47 @@ This section provides instructions on how to get started with Nyxstone, covering

### Prerequisites

Before building Nyxstone, ensure clang and LLVM 15 are present as statically linked libraries. Nyxstone looks for `llvm-config` in your system's `$PATH` or the specified environment variable `$NYXSTONE_LLVM_PREFIX/bin`.
Before building Nyxstone, ensure clang and LLVM are present on your system. Nyxstone supports LLVM major versions 15-18.
When building it looks for `llvm-config` in your system's `$PATH` or the specified environment variable `$NYXSTONE_LLVM_PREFIX/bin`.

Installation Options for LLVM 15:
Installation Options for LLVM versions 15-18:

* Debian/Ubuntu
* Ubuntu
```bash
sudo apt install llvm-15 llvm-15-dev
export NYXSTONE_LLVM_PREFIX=/usr/lib/llvm-15/
sudo apt install llvm-${version} llvm-${version}-dev
```

* Debian
LLVM version 15 and 16 are available through debian repositories. Installation is the same as for Ubuntu.
For versions 17 or 18 refer to [https://apt.llvm.org/](https://apt.llvm.org/) for installation instructions.

* Arch
```bash
sudo pacman -S llvm llvm-libs
```

* Homebrew (macOS, Linux and others):
```bash
brew install llvm@15
export NYXSTONE_LLVM_PREFIX=/opt/homebrew/opt/llvm@15
brew install llvm@18
export NYXSTONE_LLVM_PREFIX=/opt/homebrew/opt/llvm@18
```

* From LLVM Source:

_Note_: On Windows you need to run these commands from a Visual Studio 2022 x64 command prompt. Additionally replace `~lib/my-llvm-15` with a different path.
_Note_: On Windows you need to run these commands from a Visual Studio 2022 x64 command prompt. Additionally replace `~lib/my-llvm-18` with a different path.

```bash
# checkout llvm
git clone -b release/15.x --single-branch https://github.com/llvm/llvm-project.git
git clone -b release/18.x --single-branch https://github.com/llvm/llvm-project.git
cd llvm-project

# build LLVM with custom installation directory
cmake -S llvm -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_PARALLEL_LINK_JOBS=1
cmake --build build
cmake --install build --prefix ~/lib/my-llvm-15
cmake --install build --prefix ~/lib/my-llvm-18

# export path
export NYXSTONE_LLVM_PREFIX=~/lib/my-llvm-15
export NYXSTONE_LLVM_PREFIX=~/lib/my-llvm-18
```

Also make sure to install any system dependent libraries needed by your LLVM version for static linking. They can be viewed with the command `llvm-config --system-libs`; the list can be empty. On Ubuntu/Debian, you will need the packages `zlib1g-dev` and `zlibstd-dev`.
Expand Down Expand Up @@ -169,7 +178,7 @@ $ ./nyxstone -p "0x1000" -l ".label=0x1238" "jmp .label"

### C++ Library

To use Nyxstone as a C++ library, your C++ code has to be linked against Nyxstone and LLVM 15.
To use Nyxstone as a C++ library, your C++ code has to be linked against Nyxstone and LLVM.

The following cmake example assumes Nyxstone in a subdirectory `nyxstone` in your project:

Expand Down Expand Up @@ -321,3 +330,6 @@ The current contributors are:
* Marc Fyrbiak (emproof)
* Tim Blazytko (emproof)

## Acknowledgements

To ensure that we link LLVM correctly with proper versioning in Rust, we adapted the build.rs from [llvm-sys](https://gitlab.com/taricorp/llvm-sys.rs/).
2 changes: 1 addition & 1 deletion bindings/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

## Installation

You need to have LLVM 15 (with static library support) installed to build the nyxstone bindings. The `setup.py` searches for LLVM in the `PATH` or in the directory set in the environment variable `NYXSTONE_LLVM_PREFIX`. Specifically, it searches for the binary `$NYXSTONE_LLVM_PREFIX/bin/llvm-config` and uses it to set the required libraries and cpp flags.
You need to have LLVM (with major version in the range 15-18) installed to build the nyxstone bindings. The `setup.py` searches for LLVM in the `PATH` or in the directory set in the environment variable `NYXSTONE_LLVM_PREFIX`. Specifically, it searches for the binary `$NYXSTONE_LLVM_PREFIX/bin/llvm-config` and uses it to set the required libraries and cpp flags.

Running

Expand Down
Loading

0 comments on commit e0fa780

Please sign in to comment.