Skip to content

Instantly share code, notes, and snippets.

@andrewrk
Created November 20, 2020 21:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrewrk/388c97fb525ee4f1769db5bf79ed86c9 to your computer and use it in GitHub Desktop.
Save andrewrk/388c97fb525ee4f1769db5bf79ed86c9 to your computer and use it in GitHub Desktop.
experimenting with reloading a static binary to make it dynamic
#include <stdbool.h>
#include <stddef.h>
void __attribute__((weak)) dlopen(const char *filename, int flags);
int __attribute__((weak)) dlclose(void *handle);
struct ZigWindowFns {
void (*dlopen)(const char *filename, int flags);
int (*dlclose)(void *handle);
};
static struct ZigWindowFns global_fns;
struct ZigWindowFns *zig_window_get_fns(void) {
if (!dlopen) return NULL;
global_fns.dlopen = dlopen;
global_fns.dlclose = dlclose;
return &global_fns;
}
const std = @import("std");
const ZigWindowFns = extern struct {
dlopen: fn ([*:0]const u8, c_int) callconv(.C) void,
dlclose: fn (?*c_void) callconv(.C) c_int,
};
extern fn zig_window_get_fns() ?*ZigWindowFns;
var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
pub fn main() anyerror!void {
const gpa = &general_purpose_allocator.allocator;
defer _ = general_purpose_allocator.deinit();
var arena_instance = std.heap.ArenaAllocator.init(gpa);
defer arena_instance.deinit();
const arena = &arena_instance.allocator;
std.log.debug("detecting whether we are running in the dynamic linker", .{});
const fns = zig_window_get_fns() orelse {
std.log.debug("we're not. detecting the dynamic linker path", .{});
const info = try std.zig.system.NativeTargetInfo.detect(arena, .{});
const dyld_path = info.dynamic_linker.get() orelse @panic("OS has no dynamic linker");
std.log.debug("dyld_path={}", .{dyld_path});
const dyld_z = arena.dupeZ(u8, dyld_path) catch @panic("out of memory");
const argv = arena.allocSentinel(?[*:0]const u8, std.os.argv.len + 1, null) catch @panic("out of memory");
argv[0] = dyld_z;
for (std.os.argv) |arg, i| {
argv[i + 1] = arg;
}
// TODO make std.os.environ slice be also null terminated
const envp = @ptrCast([*:null]const ?[*:0]const u8, std.os.environ.ptr);
return std.os.execveZ(dyld_z, argv, envp);
};
std.log.debug("got the fns", .{});
// So far our goal is to call these 2 functions.
//XInitThreads();
//XrmInitialize();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment