Skip to content

Commit

Permalink
fix: override C++ allocation functions by Rust implementation
Browse files Browse the repository at this point in the history
Previously, the overriding implementations were defined in a C++ source
file compiled and linked by the use of `cc`. It didn't really work because
their symbols weren't exported by the final cdylib file. This commit works
around the issue by re-implementing them in Rust code. This is a sketchy
hack at best since it makes assumptions about the target environment's C++
mangling scheme and calling conventions.

This might be made unnecessary by [rust-lang/rfcs#2771][1].

[1]: rust-lang/rfcs#2771
  • Loading branch information
yvt committed Jul 9, 2022
1 parent 85e7837 commit e88132a
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 98 deletions.
4 changes: 0 additions & 4 deletions .clang-format

This file was deleted.

7 changes: 0 additions & 7 deletions Cargo.lock

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

3 changes: 0 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ crate-type = ["cdylib"]
libc = { version = "0.2.126", default-features = false }
rlsf = "0.1.2"

[build-dependencies]
cc = "1.0"

[profile.dev]
panic = "abort"

Expand Down
6 changes: 0 additions & 6 deletions build.rs

This file was deleted.

78 changes: 0 additions & 78 deletions src/ovrride.cpp

This file was deleted.

144 changes: 144 additions & 0 deletions src/ovrride.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,147 @@ pub unsafe extern "C" fn free(ptr: *mut c_void) {
CAlloc::deallocate(&ALLOC, ptr.cast());
}
}

// TODO: Find a way to define these in a C++ source file and make sure the
// symbols are exported by the final cdylib file
/// `operator delete[](void*, unsigned long, std::align_val_t)`
#[no_mangle]
pub unsafe extern "C" fn _ZdaPvmSt11align_val_t(p: *mut c_void, _: usize, _: usize) {
free(p);
}

/// `operator delete[](void*, std::align_val_t, std::nothrow_t const&)`
#[no_mangle]
pub unsafe extern "C" fn _ZdaPvSt11align_val_tRKSt9nothrow_t(p: *mut c_void, _: usize, _: &c_void) {
free(p);
}

/// `operator delete[](void*, std::align_val_t)`
#[no_mangle]
pub unsafe extern "C" fn _ZdaPvSt11align_val_t(p: *mut c_void, _: usize) {
free(p);
}

/// `operator delete(void*, unsigned long, std::align_val_t)`
#[no_mangle]
pub unsafe extern "C" fn _ZdlPvmSt11align_val_t(p: *mut c_void, _: usize, _: usize) {
free(p);
}

/// `operator delete(void*, std::align_val_t, std::nothrow_t const&)`
#[no_mangle]
pub unsafe extern "C" fn _ZdlPvSt11align_val_tRKSt9nothrow_t(p: *mut c_void, _: usize, _: usize) {
free(p);
}

/// `operator delete(void*, std::align_val_t)`
#[no_mangle]
pub unsafe extern "C" fn _ZdlPvSt11align_val_t(p: *mut c_void, _: usize) {
free(p);
}

/// `operator new[](unsigned long, std::align_val_t, std::nothrow_t const&)`
#[no_mangle]
pub unsafe extern "C" fn _ZnamSt11align_val_tRKSt9nothrow_t(
size: usize,
align: usize,
_: &c_void,
) -> *mut c_void {
cpp_new_impl(size, align, true)
}

/// `operator new[](unsigned long, std::align_val_t)`
#[no_mangle]
pub unsafe extern "C" fn _ZnamSt11align_val_t(size: usize, align: usize) -> *mut c_void {
cpp_new_impl(size, align, false)
}

/// `operator new(unsigned long, std::align_val_t, std::nothrow_t const&)`
#[no_mangle]
pub unsafe extern "C" fn _ZnwmSt11align_val_tRKSt9nothrow_t(
size: usize,
align: usize,
_: &c_void,
) -> *mut c_void {
cpp_new_impl(size, align, true)
}

/// `operator new(unsigned long, std::align_val_t)`
#[no_mangle]
pub unsafe extern "C" fn _ZnwmSt11align_val_t(size: usize, align: usize) -> *mut c_void {
cpp_new_impl(size, align, false)
}

/// `operator delete[](void*, unsigned long)`
#[no_mangle]
pub unsafe extern "C" fn _ZdaPvm(p: *mut c_void, _: usize) {
free(p);
}

/// `operator delete(void*, unsigned long)`
#[no_mangle]
pub unsafe extern "C" fn _ZdlPvm(p: *mut c_void, _: usize) {
free(p);
}

/// `operator delete[](void*, std::nothrow_t const&)`
#[no_mangle]
pub unsafe extern "C" fn _ZdaPvRKSt9nothrow_t(p: *mut c_void, _: &c_void) {
free(p);
}

/// `operator delete(void*, std::nothrow_t const&)`
#[no_mangle]
pub unsafe extern "C" fn _ZdlPvRKSt9nothrow_t(p: *mut c_void, _: &c_void) {
free(p);
}

/// `operator delete[](void*)`
#[no_mangle]
pub unsafe extern "C" fn _ZdaPv(p: *mut c_void) {
free(p);
}

/// `operator delete(void*)`
#[no_mangle]
pub unsafe extern "C" fn _ZdlPv(p: *mut c_void) {
free(p);
}

/// `operator new[](unsigned long, std::nothrow_t const&)`
#[no_mangle]
pub unsafe extern "C" fn _ZnamRKSt9nothrow_t(size: usize, _: &c_void) -> *mut c_void {
cpp_new_impl(size, 0, true)
}

/// `operator new(unsigned long, std::nothrow_t const&)`
#[no_mangle]
pub unsafe extern "C" fn _ZnwmRKSt9nothrow_t(size: usize, _: &c_void) -> *mut c_void {
cpp_new_impl(size, 0, true)
}

/// `operator new[](unsigned long)`
#[no_mangle]
pub unsafe extern "C" fn _Znam(size: usize) -> *mut c_void {
cpp_new_impl(size, 0, false)
}

/// `operator new(unsigned long)`
#[no_mangle]
pub unsafe extern "C" fn _Znwm(size: usize) -> *mut c_void {
cpp_new_impl(size, 0, false)
}

fn cpp_new_impl(size: usize, align: usize, is_noexcept: bool) -> *mut c_void {
let ptr = unsafe {
if align == 0 {
malloc(size)
} else {
aligned_alloc(align, size)
}
};
if !is_noexcept && ptr.is_null() {
panic!("allocation of size {size} and alignment {align} failed");
}
ptr
}

0 comments on commit e88132a

Please sign in to comment.