Commit 07dfccf967

LemonBoy <thatlemon@gmail.com>
2019-05-05 12:14:53
Review
1 parent e4825db
Changed files (3)
std/c/linux.zig
@@ -1,3 +1,4 @@
+const linux = @import("../os/linux.zig");
 pub use @import("../os/linux/errno.zig");
 
 pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) c_int;
@@ -12,4 +13,5 @@ pub const pthread_attr_t = extern struct {
 /// See std.elf for constants for this
 pub extern fn getauxval(__type: c_ulong) c_ulong;
 
-pub extern fn dl_iterate_phdr(callback: *const c_void, data: ?*c_void) i32;
+pub const dl_iterate_phdr_callback = extern fn (info: *linux.dl_phdr_info, size: usize, data: ?*c_void) c_int;
+pub extern fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int;
std/os/linux.zig
@@ -4,6 +4,7 @@ const builtin = @import("builtin");
 const maxInt = std.math.maxInt;
 const elf = std.elf;
 const vdso = @import("linux/vdso.zig");
+const dl = @import("../dynamic_library.zig");
 pub use switch (builtin.arch) {
     builtin.Arch.x86_64 => @import("linux/x86_64.zig"),
     builtin.Arch.i386 => @import("linux/i386.zig"),
@@ -1537,33 +1538,32 @@ pub const dirent64 = extern struct {
 
 pub const dl_phdr_info = extern struct {
     dlpi_addr: usize,
-    dlpi_name: [*c]const u8,
-    dlpi_phdr: [*c]*c_void,
+    dlpi_name: ?[*]const u8,
+    dlpi_phdr: [*]elf.Phdr,
     dlpi_phnum: u16,
 };
 
-const DynLib = @import("../dynamic_library.zig");
-
 // XXX: This should be weak
 extern const __ehdr_start: elf.Ehdr = undefined;
 
-pub fn dl_iterate_phdr(callback: extern fn (info: *dl_phdr_info, size: usize, data: ?*c_void) i32, data: ?*c_void) isize {
+pub fn dl_iterate_phdr(comptime T: type, callback: extern fn (info: *dl_phdr_info, size: usize, data: ?*T) i32, data: ?*T) isize {
     if (builtin.link_libc) {
-        return std.c.dl_iterate_phdr(@ptrCast(*const c_void, callback), data);
+        return std.c.dl_iterate_phdr(@ptrCast(std.c.dl_iterate_phdr_callback, callback), @ptrCast(?*c_void, data));
     }
 
     const elf_base = @ptrToInt(&__ehdr_start);
     const n_phdr = __ehdr_start.e_phnum;
     const phdrs = (@intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff))[0..n_phdr];
 
-    var it = DynLib.linkmap_iterator(phdrs) catch return 0;
+    var it = dl.linkmap_iterator(phdrs) catch return 0;
+
+    // The executable has no dynamic link segment, create a single entry for
+    // the whole ELF image
     if (it.end()) {
-        // The executable has no dynamic link infos, create a single info
-        // struct for the whole ELF image
         var info = dl_phdr_info{
             .dlpi_addr = elf_base,
             .dlpi_name = c"/proc/self/exe",
-            .dlpi_phdr = @intToPtr([*c]*c_void, elf_base + __ehdr_start.e_phoff),
+            .dlpi_phdr = @intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff),
             .dlpi_phnum = __ehdr_start.e_phnum,
         };
 
@@ -1573,23 +1573,26 @@ pub fn dl_iterate_phdr(callback: extern fn (info: *dl_phdr_info, size: usize, da
     // Last return value from the callback function
     var last_r: isize = 0;
     while (it.next()) |entry| {
-        var info = dl_phdr_info{
-            .dlpi_addr = entry.l_addr,
-            .dlpi_name = entry.l_name,
-            .dlpi_phdr = 0,
-            .dlpi_phnum = 0,
-        };
+        var dlpi_phdr: usize = undefined;
+        var dlpi_phnum: u16 = undefined;
 
         if (entry.l_addr != 0) {
             const elf_header = @intToPtr(*elf.Ehdr, entry.l_addr);
-            info.dlpi_phdr = @intToPtr([*c]*c_void, entry.l_addr + elf_header.e_phoff);
-            info.dlpi_phnum = elf_header.e_phnum;
+            dlpi_phdr = entry.l_addr + elf_header.e_phoff;
+            dlpi_phnum = elf_header.e_phnum;
         } else {
             // This is the running ELF image
-            info.dlpi_phdr = @intToPtr([*c]*c_void, elf_base + __ehdr_start.e_phoff);
-            info.dlpi_phnum = __ehdr_start.e_phnum;
+            dlpi_phdr = elf_base + __ehdr_start.e_phoff;
+            dlpi_phnum = __ehdr_start.e_phnum;
         }
 
+        var info = dl_phdr_info{
+            .dlpi_addr = entry.l_addr,
+            .dlpi_name = entry.l_name,
+            .dlpi_phdr = @intToPtr([*]elf.Phdr, dlpi_phdr),
+            .dlpi_phnum = dlpi_phnum,
+        };
+
         last_r = callback(&info, @sizeOf(dl_phdr_info), data);
         if (last_r != 0) break;
     }
std/dynamic_library.zig
@@ -19,25 +19,29 @@ pub const DynLib = switch (builtin.os) {
     else => void,
 };
 
+// The link_map structure is not completely specified beside the fields
+// reported below, any libc is free to store additional data in the remaining
+// space.
+// An iterator is provided in order to traverse the linked list in a idiomatic
+// fashion.
 const LinkMap = extern struct {
     l_addr: usize,
-    l_name: [*]u8,
-    l_ld: [*c]elf.Dyn,
-    l_next: [*c]LinkMap,
-    l_prev: [*c]LinkMap,
+    l_name: [*]const u8,
+    l_ld: ?*elf.Dyn,
+    l_next: ?*LinkMap,
+    l_prev: ?*LinkMap,
 
     pub const Iterator = struct {
-        lm_ptr: [*c]LinkMap,
+        current: ?*LinkMap,
 
-        fn end(self: *const Iterator) bool {
-            return self.lm_ptr == 0;
+        fn end(self: *Iterator) bool {
+            return self.current == null;
         }
 
         fn next(self: *Iterator) ?*LinkMap {
-            if (self.lm_ptr != 0) {
-                const ptr = self.lm_ptr;
-                self.lm_ptr = self.lm_ptr.*.l_next;
-                return ptr;
+            if (self.current) |it| {
+                self.current = it.l_next;
+                return it;
             }
             return null;
         }
@@ -46,7 +50,7 @@ const LinkMap = extern struct {
 
 const RDebug = extern struct {
     r_version: i32,
-    r_map: [*c]LinkMap,
+    r_map: ?*LinkMap,
     r_brk: usize,
     r_ldbase: usize,
 };
@@ -72,7 +76,7 @@ pub fn linkmap_iterator(phdrs: []elf.Phdr) !LinkMap.Iterator {
         }
         // No PT_DYNAMIC means this is either a statically-linked program or a
         // badly corrupted one
-        return LinkMap.Iterator{.lm_ptr = 0};
+        return LinkMap.Iterator{.current = null};
     };
 
     const link_map_ptr = init: {
@@ -87,7 +91,7 @@ pub fn linkmap_iterator(phdrs: []elf.Phdr) !LinkMap.Iterator {
                     const got_table = @intToPtr([*]usize, dyn.d_un.d_ptr);
                     // The address to the link_map structure is stored in the
                     // second slot
-                    break :init @intToPtr([*c]LinkMap, got_table[1]);
+                    break :init @intToPtr(?*LinkMap, got_table[1]);
                 },
                 else => { }
             }
@@ -95,7 +99,7 @@ pub fn linkmap_iterator(phdrs: []elf.Phdr) !LinkMap.Iterator {
         return error.InvalidExe;
     };
 
-    return LinkMap.Iterator{.lm_ptr = link_map_ptr};
+    return LinkMap.Iterator{.current = link_map_ptr};
 }
 
 pub const LinuxDynLib = struct {