Skip to content

Commit

Permalink
Add dyld helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
LunaTheFoxgirl committed Jan 1, 2025
1 parent e330a66 commit 34d952d
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 3 deletions.
155 changes: 155 additions & 0 deletions source/os/mach/dyld.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*
Copyright © 2024, Kitsunebi Games EMV
Distributed under the Boost Software License, Version 1.0,
see LICENSE file.
Authors: Luna Nielsen
*/

/**
Extensions to dyld API.
*/
module os.mach.dyld;
import dyld = core.sys.darwin.mach.dyld;
import core.sys.darwin.dlfcn;
import core.sys.darwin.mach.loader;
import core.sys.darwin.mach.dyld :
_dyld_get_image_header,
_dyld_get_image_name,
_dyld_image_count;

version (OSX)
version = Darwin;
else version (iOS)
version = Darwin;
else version (TVOS)
version = Darwin;
else version (WatchOS)
version = Darwin;

version (Darwin):
extern (C) nothrow @nogc:

/**
32-bit mach header.
*/
alias mach_header_32 = dyld.mach_header;

/**
64-bit mach header.
*/
alias mach_header_64 = dyld.mach_header_64;

/**
32-bit mach section.
*/
alias mach_section_32 = dyld.section;

/**
64-bit mach section.
*/
alias mach_section_64 = dyld.section_64;

/**
32-bit mach section.
*/
alias mach_segment_32 = dyld.segment_command;

/**
64-bit mach section.
*/
alias mach_segment_64 = dyld.segment_command_64;

/**
A mach header which matches the current device's architecture.
*/
version(D_LP64) alias mach_header = mach_header_64;
else alias mach_header = mach_header_32;

/**
A mach section which matches the current device's architecture.
*/
version(D_LP64) alias mach_section = mach_section_64;
else alias mach_section = mach_section_32;

/**
A mach segment which matches the current device's architecture.
*/
version(D_LP64) alias mach_segment = mach_segment_64;
else alias mach_segment = mach_segment_32;

// Mask value for the mode value added to a dlopen handle.
enum size_t RTLD_MODEMASK = cast(size_t)-4;

/**
Attempt to find a mach_header from its dlopen handle.
Returns: mach_header address or `null` on failure.
*/
const(mach_header)* dyld_get_dlopen_image_header(void* handle) {
auto idx = dylib_get_dlopen_image_index(handle);
if (idx >= 0) {
return cast(const(mach_header)*)_dyld_get_image_header(cast(uint)idx);
}
return null;
}

/**
Attempts to get the image path of a dlopen handle.
Returns: Image path on success, `null` on failure.
*/
const(char)* dylib_get_dlopen_image_path(void* handle) {
auto idx = dylib_get_dlopen_image_index(handle);
if (idx >= 0) {
return _dyld_get_image_name(cast(uint)idx);
}
return null;
}

/**
Attempts to get the image index of a dlopen handle.
Returns: Image index on success, `-1` on failure.
*/
ptrdiff_t dylib_get_dlopen_image_index(void* handle) {
foreach(i; 0.._dyld_image_count()) {

// By passing RTLD_NOLOAD we won't be attempting to
// load an unloaded library.
// This prevents oopsies where you're trying to get the index
// of an image that is somehow not loaded (name mismatch??)
const(char)* name = _dyld_get_image_name(i);
if (void* probeHandle = dlopen(name, RTLD_NOLOAD | RTLD_LAZY)) {
dlclose(probeHandle);

// We strip the mode bits off the handle.
// So that we can match handles despite which RTLD parameters were passed.
if ((cast(size_t)handle & RTLD_MODEMASK) ==
(cast(size_t)probeHandle & RTLD_MODEMASK))
return i;
}
}
return -1;
}

/**
Finds dlopen handle associated with the given mach_header.
Returns: Handle on success, `-1` on failure.
*/
void* dylib_get_handle_for_header(const(mach_header)* header) {
Dl_info info;
if (dladdr(header, &info)) {

// Lookup the handle by getting the dli_fname from the header.
// since the header is located *within* the address space of
// the dylib.
void* handle = dlopen(info.dli_fname, RTLD_NOLOAD | RTLD_LAZY);
dlclose(handle);
return handle;
}

// Not found.
return null;
}
18 changes: 15 additions & 3 deletions source/mach/ports.d → source/os/mach/ports.d
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,29 @@
/**
Mach Ports bindings
*/
module mach.ports;
module os.mach.ports;
import objc.os;

extern(C) nothrow @nogc:
version (OSX)
version = Darwin;
else version (iOS)
version = Darwin;
else version (TVOS)
version = Darwin;
else version (WatchOS)
version = Darwin;

version (Darwin):
extern (C) nothrow @nogc:

// Contains definitions for mach_port_t and natural_t.
public import core.sys.darwin.mach.port;

public import core.sys.darwin.mach.kern_return;
public import core.sys.darwin.mach.semaphore;

/// IPC Space
struct ipc_space;
struct ipc_space; // @suppress(dscanner.style.phobos_naming_convention)
alias ipc_space_t = ipc_space*;

/**
Expand Down

0 comments on commit 34d952d

Please sign in to comment.