authorgravatar for emekankurumeh@outlook.comemekoi <emekankurumeh@outlook.com> 2019-05-30 20:03:56-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-10 11:41:54-05:00
log29fd727b79682a0f3e8ad7340cf86db989b9109e
tree4614be3e4449817c7d508e70858aa77a8fbaf1c8
parent9561e7c6b9fb2d9ebcbfd611196db698372ae7bd
signature Commit is signed but in an unrecognized format.

fixed windows dynamic library loading and added loading for darwin


4 files changed, 103 insertions(+), 14 deletions(-)

lib/std/c/darwin.zig+4
...@@ -128,3 +128,7 @@ pub const pthread_attr_t = extern struct {...@@ -128,3 +128,7 @@ pub const pthread_attr_t = extern struct {
128 __sig: c_long,128 __sig: c_long,
129 __opaque: [56]u8,129 __opaque: [56]u8,
130};130};
131
132pub extern "c" fn dlopen(path: [*]const u8, mode: c_int) ?*c_void;
133pub extern "c" fn dlclose(handle: *c_void) c_int;
134pub extern "c" fn dlsym(handle: ?*c_void, symbol: [*]const u8) ?*c_void;
lib/std/dynamic_library.zig+80-10
...@@ -7,11 +7,13 @@ const assert = std.debug.assert;...@@ -7,11 +7,13 @@ const assert = std.debug.assert;
7const testing = std.testing;7const testing = std.testing;
8const elf = std.elf;8const elf = std.elf;
9const windows = std.os.windows;9const windows = std.os.windows;
10const system = std.os.system;
10const maxInt = std.math.maxInt;11const maxInt = std.math.maxInt;
1112
12pub const DynLib = switch (builtin.os) {13pub const DynLib = switch (builtin.os) {
13 .linux => LinuxDynLib,14 .linux => if (builtin.link_libc) DlDynlib else LinuxDynLib,
14 .windows => WindowsDynLib,15 .windows => WindowsDynLib,
16 .macosx, .tvos, .watchos, .ios => DlDynlib,
15 else => void,17 else => void,
16};18};
1719
...@@ -99,12 +101,14 @@ pub fn linkmap_iterator(phdrs: []elf.Phdr) !LinkMap.Iterator {...@@ -99,12 +101,14 @@ pub fn linkmap_iterator(phdrs: []elf.Phdr) !LinkMap.Iterator {
99}101}
100102
101pub const LinuxDynLib = struct {103pub const LinuxDynLib = struct {
104 pub const Error = ElfLib.Error;
105
102 elf_lib: ElfLib,106 elf_lib: ElfLib,
103 fd: i32,107 fd: i32,
104 memory: []align(mem.page_size) u8,108 memory: []align(mem.page_size) u8,
105109
106 /// Trusts the file110 /// Trusts the file
107 pub fn open(path: []const u8) !DynLib {111 pub fn open(path: []const u8) !LinuxDynLib {
108 const fd = try os.open(path, 0, os.O_RDONLY | os.O_CLOEXEC);112 const fd = try os.open(path, 0, os.O_RDONLY | os.O_CLOEXEC);
109 errdefer os.close(fd);113 errdefer os.close(fd);
110114
...@@ -121,26 +125,42 @@ pub const LinuxDynLib = struct {...@@ -121,26 +125,42 @@ pub const LinuxDynLib = struct {
121 );125 );
122 errdefer os.munmap(bytes);126 errdefer os.munmap(bytes);
123127
124 return DynLib{128 return LinuxDynLib{
125 .elf_lib = try ElfLib.init(bytes),129 .elf_lib = try ElfLib.init(bytes),
126 .fd = fd,130 .fd = fd,
127 .memory = bytes,131 .memory = bytes,
128 };132 };
129 }133 }
130134
131 pub fn close(self: *DynLib) void {135 pub fn close(self: *LinuxDynLib) void {
132 os.munmap(self.memory);136 os.munmap(self.memory);
133 os.close(self.fd);137 os.close(self.fd);
134 self.* = undefined;138 self.* = undefined;
135 }139 }
136140
137 pub fn lookup(self: *DynLib, name: []const u8) ?usize {141 pub fn lookup(self: *LinuxDynLib, comptime T: type, name: []const u8) ?T {
138 return self.elf_lib.lookup("", name);142 if (self.elf_lib.lookup("", name)) |symbol| {
143 return @ptrCast(T, symbol);
144 } else {
145 return null;
146 }
139 }147 }
140};148};
141149
142pub const ElfLib = struct {150pub const ElfLib = struct {
143 strings: [*:0]u8,151 strings: [*:0]u8,
152
153 pub const Error = error{
154 NotElfFile,
155 NotDynamicLibrary,
156 MissingDynamicLinkingInformation,
157 BaseNotFound,
158 ElfStringSectionNotFound,
159 ElfSymSectionNotFound,
160 ElfHashTableNotFound,
161 };
162
163 strings: [*]u8,
144 syms: [*]elf.Sym,164 syms: [*]elf.Sym,
145 hashtab: [*]os.Elf_Symndx,165 hashtab: [*]os.Elf_Symndx,
146 versym: ?[*]u16,166 versym: ?[*]u16,
...@@ -245,11 +265,12 @@ fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [...@@ -245,11 +265,12 @@ fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [
245}265}
246266
247pub const WindowsDynLib = struct {267pub const WindowsDynLib = struct {
268 pub const Error = error{FileNotFound};
269
248 dll: windows.HMODULE,270 dll: windows.HMODULE,
249271
250 pub fn open(path: []const u8) !WindowsDynLib {272 pub fn open(path: []const u8) !WindowsDynLib {
251 const wpath = try windows.sliceToPrefixedFileW(path);273 const wpath = try windows.sliceToPrefixedFileW(path);
252
253 return WindowsDynLib{274 return WindowsDynLib{
254 .dll = try windows.LoadLibraryW(&wpath),275 .dll = try windows.LoadLibraryW(&wpath),
255 };276 };
...@@ -260,8 +281,57 @@ pub const WindowsDynLib = struct {...@@ -260,8 +281,57 @@ pub const WindowsDynLib = struct {
260 self.* = undefined;281 self.* = undefined;
261 }282 }
262283
263 pub fn lookup(self: *WindowsDynLib, name: []const u8) ?usize {284 pub fn lookupC(self: *WindowsDynLib, comptime T: type, name: [*:0]const u8) ?T {
264 return @ptrToInt(windows.kernel32.GetProcAddress(self.dll, name.ptr));285 if (windows.kernel32.GetProcAddress(self.dll, name)) |addr| {
286 return @ptrCast(T, addr);
287 } else {
288 return null;
289 }
290 }
291
292 pub fn lookup(self: *DlDynlib, comptime T: type, comptime max_name_len: usize, name: []const u8) ?T {
293 const c_name: [max_name_len]u8 = undefined;
294 mem.copy(&c_name, name);
295 c_name[name.len] = 0;
296 return self.lookupC(T, &c_name);
297 }
298};
299
300pub const DlDynlib = struct {
301 pub const Error = error{FileNotFound};
302
303 handle: *c_void,
304
305 pub fn open(path: []const u8) !DlDynlib {
306 if (!builtin.link_libc and !os.darwin.is_the_target) {
307 @compileError("DlDynlib requires libc");
308 }
309
310 return DlDynlib{
311 .handle = system.dlopen(path.ptr, system.RTLD_LAZY) orelse {
312 return error.FileNotFound;
313 },
314 };
315 }
316
317 pub fn close(self: *DlDynlib) void {
318 _ = system.dlclose(self.handle);
319 self.* = undefined;
320 }
321
322 pub fn lookupC(self: *DlDynlib, comptime T: type, name: [*:0]const u8) ?T {
323 if (system.dlsym(self.handle, name)) |symbol| {
324 return @ptrCast(T, symbol);
325 } else {
326 return null;
327 }
328 }
329
330 pub fn lookup(self: *DlDynlib, comptime T: type, comptime max_name_len: usize, name: []const u8) ?T {
331 const c_name: [max_name_len]u8 = undefined;
332 mem.copy(&c_name, name);
333 c_name[name.len] = 0;
334 return self.lookupC(T, &c_name);
265 }335 }
266};336};
267337
...@@ -269,6 +339,7 @@ test "dynamic_library" {...@@ -269,6 +339,7 @@ test "dynamic_library" {
269 const libname = switch (builtin.os) {339 const libname = switch (builtin.os) {
270 .linux => "invalid_so.so",340 .linux => "invalid_so.so",
271 .windows => "invalid_dll.dll",341 .windows => "invalid_dll.dll",
342 .macosx, .tvos, .watchos, .ios => "invalid_dylib.dylib",
272 else => return,343 else => return,
273 };344 };
274345
...@@ -276,5 +347,4 @@ test "dynamic_library" {...@@ -276,5 +347,4 @@ test "dynamic_library" {
276 testing.expect(err == error.FileNotFound);347 testing.expect(err == error.FileNotFound);
277 return;348 return;
278 };349 };
279 @panic("Expected error from function");
280}350}
lib/std/os/bits/darwin.zig+14
...@@ -1183,6 +1183,7 @@ pub fn S_ISSOCK(m: u32) bool {...@@ -1183,6 +1183,7 @@ pub fn S_ISSOCK(m: u32) bool {
1183pub fn S_IWHT(m: u32) bool {1183pub fn S_IWHT(m: u32) bool {
1184 return m & S_IFMT == S_IFWHT;1184 return m & S_IFMT == S_IFWHT;
1185}1185}
1186
1186pub const HOST_NAME_MAX = 72;1187pub const HOST_NAME_MAX = 72;
11871188
1188pub const AT_FDCWD = -2;1189pub const AT_FDCWD = -2;
...@@ -1209,3 +1210,16 @@ pub const addrinfo = extern struct {...@@ -1209,3 +1210,16 @@ pub const addrinfo = extern struct {
1209 addr: ?*sockaddr,1210 addr: ?*sockaddr,
1210 next: ?*addrinfo,1211 next: ?*addrinfo,
1211};1212};
1213
1214pub const RTLD_LAZY = 0x1;
1215pub const RTLD_NOW = 0x2;
1216pub const RTLD_LOCAL = 0x4;
1217pub const RTLD_GLOBAL = 0x8;
1218pub const RTLD_NOLOAD = 0x10;
1219pub const RTLD_NODELETE = 0x80;
1220pub const RTLD_FIRST = 0x100;
1221
1222pub const RTLD_NEXT = @intToPtr(*c_void, ~maxInt(usize));
1223pub const RTLD_DEFAULT = @intToPtr(*c_void, ~maxInt(usize) - 1);
1224pub const RTLD_SELF = @intToPtr(*c_void, ~maxInt(usize) - 2);
1225pub const RTLD_MAIN_ONLY = @intToPtr(*c_void, ~maxInt(usize) - 4);
test/standalone.zig+5-4
...@@ -19,10 +19,11 @@ pub fn addCases(cases: *tests.StandaloneContext) void {...@@ -19,10 +19,11 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
19 cases.addBuildFile("test/standalone/use_alias/build.zig");19 cases.addBuildFile("test/standalone/use_alias/build.zig");
20 cases.addBuildFile("test/standalone/brace_expansion/build.zig");20 cases.addBuildFile("test/standalone/brace_expansion/build.zig");
21 cases.addBuildFile("test/standalone/empty_env/build.zig");21 cases.addBuildFile("test/standalone/empty_env/build.zig");
22 if (builtin.os == builtin.Os.linux) {22 switch (builtin.os) {
23 // TODO hook up the DynLib API for windows using LoadLibraryA23 .linux, .windows, .macosx, .tvos, .watchos, .ios => {
24 // TODO figure out how to make this work on darwin - probably libSystem has dlopen/dlsym in it24 cases.addBuildFile("test/standalone/load_dynamic_library/build.zig");
25 cases.addBuildFile("test/standalone/load_dynamic_library/build.zig");25 },
26 else => {},
26 }27 }
2728
28 if (builtin.arch == builtin.Arch.x86_64) { // TODO add C ABI support for other architectures29 if (builtin.arch == builtin.Arch.x86_64) { // TODO add C ABI support for other architectures