diff --git a/test/shared_library_unwind/BUILD.bazel b/test/shared_library_unwind/BUILD.bazel new file mode 100644 index 0000000..fd919e5 --- /dev/null +++ b/test/shared_library_unwind/BUILD.bazel @@ -0,0 +1,40 @@ +load("@rules_cc//cc:defs.bzl", "cc_test") +load("@rules_rs//rs:rust_shared_library.bzl", "rust_shared_library") +load("@rules_shell//shell:sh_test.bzl", "sh_test") + +_LINUX_ONLY = select({ + "@platforms//os:linux": [], + "//conditions:default": ["@platforms//:incompatible"], +}) + +rust_shared_library( + name = "filewatcher_jni", + srcs = ["filewatcher_jni.rs"], + crate_name = "filewatcher_jni", + edition = "2021", +) + +sh_test( + name = "filewatcher_jni_unwind_link_test", + srcs = ["unwind_link_test.sh"], + args = [ + "$(location :filewatcher_jni)", + "$(location @llvm//tools:llvm-nm)", + "$(location @llvm//tools:llvm-readelf)", + ], + data = [ + ":filewatcher_jni", + "@llvm//tools:llvm-nm", + "@llvm//tools:llvm-readelf", + ], + target_compatible_with = _LINUX_ONLY, +) + +cc_test( + name = "filewatcher_jni_dlopen_test", + srcs = ["dlopen_test.c"], + args = ["$(location :filewatcher_jni)"], + data = [":filewatcher_jni"], + linkopts = ["-ldl"], + target_compatible_with = _LINUX_ONLY, +) diff --git a/test/shared_library_unwind/dlopen_test.c b/test/shared_library_unwind/dlopen_test.c new file mode 100644 index 0000000..2629e9c --- /dev/null +++ b/test/shared_library_unwind/dlopen_test.c @@ -0,0 +1,24 @@ +#include +#include + +int main(int argc, char **argv) { + if (argc != 2) { + fprintf(stderr, "usage: %s \n", argv[0]); + return 2; + } + + void *handle = dlopen(argv[1], RTLD_NOW | RTLD_LOCAL); + if (!handle) { + fprintf(stderr, "dlopen failed: %s\n", dlerror()); + return 1; + } + + if (!dlsym(handle, "Java_com_example_FileWatcher_nativeInit")) { + fprintf(stderr, "dlsym failed: %s\n", dlerror()); + dlclose(handle); + return 1; + } + + dlclose(handle); + return 0; +} diff --git a/test/shared_library_unwind/filewatcher_jni.rs b/test/shared_library_unwind/filewatcher_jni.rs new file mode 100644 index 0000000..da6f726 --- /dev/null +++ b/test/shared_library_unwind/filewatcher_jni.rs @@ -0,0 +1,13 @@ +use std::ffi::c_void; + +unsafe extern "C" { + fn _Unwind_GetIP(ctx: *mut c_void) -> usize; + fn _Unwind_GetIPInfo(ctx: *mut c_void, ip_before_insn: *mut i32) -> usize; +} + +#[no_mangle] +pub extern "C" fn Java_com_example_FileWatcher_nativeInit() -> usize { + let get_ip = _Unwind_GetIP as usize; + let get_ip_info = _Unwind_GetIPInfo as usize; + get_ip ^ get_ip_info +} diff --git a/test/shared_library_unwind/unwind_link_test.sh b/test/shared_library_unwind/unwind_link_test.sh new file mode 100755 index 0000000..d344fbf --- /dev/null +++ b/test/shared_library_unwind/unwind_link_test.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -euo pipefail + +lib="$1" +llvm_nm="$2" +llvm_readelf="$3" + +undefined="$("$llvm_nm" -m -u "$lib")" +echo "$undefined" | grep '_Unwind_GetIP$' +echo "$undefined" | grep '_Unwind_GetIPInfo$' + +dynamic="$("$llvm_readelf" --dynamic "$lib")" +echo "$dynamic" | grep 'Shared library: \[libunwind\.so' +echo "$dynamic" | grep 'RUNPATH'