Skip to content

Commit

Permalink
feat: add native agent to intercept class and read annotations (#26)
Browse files Browse the repository at this point in the history
* added first version of native agent

* example added

* add test app

* add files to reproduce prototype

* up

* fix: add JVM option to compiler plugin

* initialise capabilities

* set capabilities

* attach all potential capabilities

* feat: get stack trace at runtime and print methodids

* small changes in test project

* first version rust agent

* improving code safety

* constant pool parsing in progress

* agennt c test

* update c native

* small change toy project

* refactor and fix problem in using getAnnotations()

* update commands

* rust agent in progress (fix of getAnnotations

* fix bug recursion onMethodEntry

* fix recursion problem with onMethodEntry event

* update to filter just for classportInfo annotation

* path fixing

* readme update

* code cleaning

* code cleaning

---------

Co-authored-by: serenacofano <[email protected]>
  • Loading branch information
algomaster99 and serenacofano authored Feb 17, 2025
1 parent 1a400c0 commit 87acc70
Show file tree
Hide file tree
Showing 15 changed files with 1,038 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,8 @@ target/

# vscode settings
settings.json

# Project relate files
*.so
classport-files/

16 changes: 16 additions & 0 deletions .idea/runConfigurations/AgentLoader.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

286 changes: 286 additions & 0 deletions cargo_agent/cargo_agent/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions cargo_agent/cargo_agent/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "cargo_agent"
version = "0.1.0"
edition = "2021"
build = "build.rs"

[lib]
crate-type = ["cdylib"]

[dependencies]

[build-dependencies]
bindgen = "0.71.0"

27 changes: 27 additions & 0 deletions cargo_agent/cargo_agent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## Rust Agent (WIP)
Here is an agent in Rust.

* lib.rs is the agent (for the moment just intercept onMethodEntry event and print "capitalize" when this method is intercepted);
* build.rs is the code that generate the binding of jvmti.h. It uses [rust-bindgen](https://rust-lang.github.io/rust-bindgen/)

### To use it

Requirements: see [bindgen guide](https://rust-lang.github.io/rust-bindgen/requirements.html).

- set the required environment variables

```
export JVM_LIB_PATH=<path-to-your-jdk-instalaltion>/libexec/openjdk.jdk/Contents/Home/lib/server
export JVM_INCLUDE_PATH=<path-to-jvmti.h>
export JNI_INCLUDE_PATH=<path-to-jni.h>
```

- compile the project:

`cargo build --release`

- run the agent:

`java -agentpath:/path/to/target/release/libmy_java_agent.dylib -jar your_app.jar`


29 changes: 29 additions & 0 deletions cargo_agent/cargo_agent/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use std::env;
use std::path::PathBuf;

fn main() {
println!("OUT_DIR: {}", env::var("OUT_DIR").unwrap());

let jvm_lib_path = env::var("JVM_LIB_PATH").unwrap_or_else(|_| "/usr/local/Cellar/openjdk/23.0.2/libexec/openjdk.jdk/Contents/Home/lib/server".to_string());
let jvm_include_path = env::var("JVM_INCLUDE_PATH").unwrap_or_else(|_| "/usr/local/opt/openjdk@23/include/jvmti.h".to_string());
let jni_include_path = env::var("JNI_INCLUDE_PATH").unwrap_or_else(|_| "/usr/local/opt/openjdk@23/include/jni.h".to_string());

println!("cargo:rustc-link-search={}", jvm_lib_path);
println!("cargo:rustc-link-lib=jvm");

let bindings = bindgen::Builder::default()
.header(jvm_include_path)
.header(jni_include_path)
.blocklist_function("Agent_OnLoad")
.blocklist_function("Agent_OnUnload")
// Tell cargo to invalidate the built crate whenever any of the
// included header files changed.
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.generate()
.expect("Unable to generate bindings");

let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}
Loading

0 comments on commit 87acc70

Please sign in to comment.