Skip to content

Commit 4ed079c

Browse files
committed
Add tests for unprefixed
- A test that checks that jemalloc's malloc and libc's free are interoperable when unprefixed. - A test that checks that using unprefixed with a shared library still overrides the symbols in the shared library.
1 parent 19fffb1 commit 4ed079c

File tree

7 files changed

+135
-1
lines changed

7 files changed

+135
-1
lines changed

Cargo.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11
[workspace]
2-
members = ["jemallocator", "jemallocator-global", "jemalloc-ctl", "jemalloc-sys"]
2+
members = [
3+
"jemallocator",
4+
"jemallocator-global",
5+
"jemalloc-ctl",
6+
"jemalloc-sys",
7+
"test-dylib",
8+
]

ci/run.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,14 @@ cargo test --target "${TARGET}" \
7777
# # The Alloc trait is unstable:
7878
# ${CARGO_CMD} test --target "${TARGET}" --features alloc_trait
7979
# fi
80+
81+
# Test that unprefixed_malloc_on_supported_platforms works in dylibs.
82+
case "$TARGET" in
83+
*gnu*)
84+
cargo run --target "${TARGET}" \
85+
-p test-dylib \
86+
--features unprefixed_malloc_on_supported_platforms
87+
;;
88+
*)
89+
;;
90+
esac

jemalloc-sys/tests/unprefixed_malloc.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,16 @@ fn malloc_is_prefixed() {
99
fn malloc_is_overridden() {
1010
assert_eq!(tikv_jemalloc_sys::malloc as usize, libc::malloc as usize)
1111
}
12+
13+
#[cfg(any(
14+
not(prefixed),
15+
all(
16+
feature = "unprefixed_malloc_on_supported_platforms",
17+
target_vendor = "apple"
18+
),
19+
))]
20+
#[test]
21+
fn malloc_and_libc_are_interoperable_when_overridden() {
22+
let ptr = unsafe { tikv_jemalloc_sys::malloc(42) };
23+
unsafe { libc::free(ptr) };
24+
}

test-dylib/Cargo.toml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[package]
2+
name = "test-dylib"
3+
version = "0.0.0"
4+
license = "MIT OR Apache-2.0"
5+
description = "A test helper for jemalloc-sys"
6+
edition = "2018"
7+
publish = false
8+
9+
[dependencies]
10+
libc = { version = "^0.2.8", default-features = false }
11+
tikv-jemalloc-sys = { path = "../jemalloc-sys" }
12+
13+
[build-dependencies]
14+
cc = "^1.0.13"
15+
16+
[features]
17+
unprefixed_malloc_on_supported_platforms = [
18+
"tikv-jemalloc-sys/unprefixed_malloc_on_supported_platforms",
19+
]
20+
21+
[[bin]]
22+
name = "test-dylib"
23+
test = false

test-dylib/build.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//! Build shared library `dep.c`.
2+
use std::{env, path::PathBuf};
3+
4+
fn main() {
5+
println!("cargo:rerun-if-changed=src/dep.c");
6+
7+
let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
8+
9+
// NOTE: Only for testing, extension is wrong when cross-compiling.
10+
let dylib = out_dir.join(format!(
11+
"{}dep{}",
12+
env::consts::DLL_PREFIX,
13+
env::consts::DLL_SUFFIX
14+
));
15+
16+
let status = cc::Build::new()
17+
.get_compiler()
18+
.to_command()
19+
.arg("src/dep.c")
20+
.arg("-shared")
21+
.arg("-o")
22+
.arg(&dylib)
23+
.status()
24+
.unwrap();
25+
assert!(status.success());
26+
27+
println!("cargo:rustc-link-lib=dylib=dep");
28+
println!("cargo:rustc-link-search=native={}", out_dir.display());
29+
}

test-dylib/src/dep.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#define _GNU_SOURCE
2+
#include <stdlib.h>
3+
#include <stdio.h>
4+
#include <dlfcn.h>
5+
6+
const char* lookup_malloc_address(void) {
7+
Dl_info info;
8+
if (!dladdr((void *)malloc, &info)) {
9+
printf("failed finding `malloc`\n");
10+
abort();
11+
}
12+
return info.dli_fname;
13+
}

test-dylib/src/main.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//! Test that the symbol address of `malloc` in shared libraries come from
2+
//! the place we'd expect it to.
3+
use core::ffi::{c_char, CStr};
4+
use std::{env, path::Path};
5+
6+
use tikv_jemalloc_sys as _;
7+
8+
extern "C-unwind" {
9+
fn lookup_malloc_address() -> *const c_char;
10+
}
11+
12+
fn main() {
13+
let actual = unsafe { CStr::from_ptr(lookup_malloc_address()).to_str().unwrap() };
14+
15+
if cfg!(target_vendor = "apple") {
16+
// macOS / Mach-O symbols are not overriden, they are hooked into with
17+
// `zone_register`.
18+
assert_eq!(actual, "/usr/lib/system/libsystem_malloc.dylib");
19+
} else if cfg!(all(target_os = "linux", target_env = "gnu")) {
20+
if cfg!(feature = "unprefixed_malloc_on_supported_platforms") {
21+
// When unprefixed, `malloc` is loaded from the current exe.
22+
// `target/*/debug/test-dylib`
23+
let dir = env::current_dir().unwrap();
24+
let exe = env::current_exe().unwrap();
25+
assert_eq!(Path::new(actual), exe.strip_prefix(dir).unwrap());
26+
} else if cfg!(target_arch = "x86_64") {
27+
// Otherwise, the system `libc` contains `malloc`.
28+
assert_eq!(actual, "/lib/x86_64-linux-gnu/libc.so.6");
29+
} else if cfg!(target_arch = "x86") {
30+
assert_eq!(actual, "/lib/i386-linux-gnu/libc.so.6");
31+
} else if cfg!(target_arch = "aarch64") {
32+
assert_eq!(actual, "/lib/aarch64-linux-gnu/libc.so.6");
33+
} else {
34+
panic!("unknown architecture. {:?}", actual);
35+
}
36+
} else {
37+
panic!("unsupported platform for this test. {:?}", actual);
38+
};
39+
}

0 commit comments

Comments
 (0)