diff options
| author | LemonBoy <thatlemon@gmail.com> | 2019-05-29 10:30:30 +0200 |
|---|---|---|
| committer | LemonBoy <thatlemon@gmail.com> | 2019-05-31 11:59:53 +0200 |
| commit | 46cbed621b287d339a97e77e8e1bfd5090bd247c (patch) | |
| tree | 6c9a8fd66970d5b898fd13e350faf2ed30e0a6fa /std/os.zig | |
| parent | 4b30e40a9199accee765e759bbcae133298fa54a (diff) | |
| download | zig-46cbed621b287d339a97e77e8e1bfd5090bd247c.tar.gz zig-46cbed621b287d339a97e77e8e1bfd5090bd247c.zip | |
Move dl_iterate_phdr to os.zig
Diffstat (limited to 'std/os.zig')
| -rw-r--r-- | std/os.zig | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/std/os.zig b/std/os.zig index 56a1c13dcf..cc44025031 100644 --- a/std/os.zig +++ b/std/os.zig @@ -19,6 +19,8 @@ const builtin = @import("builtin"); const assert = std.debug.assert; const math = std.math; const mem = std.mem; +const elf = std.elf; +const dl = @import("dynamic_library.zig"); const MAX_PATH_BYTES = std.fs.MAX_PATH_BYTES; comptime { @@ -2367,6 +2369,70 @@ pub fn nanosleep(seconds: u64, nanoseconds: u64) void { } } +pub fn dl_iterate_phdr(comptime T: type, callback: extern fn (info: *dl_phdr_info, size: usize, data: ?*T) i32, data: ?*T) isize { + // This is implemented only for systems using ELF executables + if (windows.is_the_target or builtin.os == .uefi or wasi.is_the_target or darwin.is_the_target) + @compileError("dl_iterate_phdr is not available for this target"); + + if (builtin.link_libc) { + return system.dl_iterate_phdr( + @ptrCast(std.c.dl_iterate_phdr_callback, callback), + @ptrCast(?*c_void, data), + ); + } + + const elf_base = std.process.getBaseAddress(); + const ehdr = @intToPtr(*elf.Ehdr, elf_base); + // Make sure the base address points to an ELF image + assert(mem.eql(u8, ehdr.e_ident[0..4], "\x7fELF")); + const n_phdr = ehdr.e_phnum; + const phdrs = (@intToPtr([*]elf.Phdr, elf_base + ehdr.e_phoff))[0..n_phdr]; + + var it = dl.linkmap_iterator(phdrs) catch unreachable; + + // The executable has no dynamic link segment, create a single entry for + // the whole ELF image + if (it.end()) { + var info = dl_phdr_info{ + .dlpi_addr = elf_base, + .dlpi_name = c"/proc/self/exe", + .dlpi_phdr = phdrs.ptr, + .dlpi_phnum = ehdr.e_phnum, + }; + + return callback(&info, @sizeOf(dl_phdr_info), data); + } + + // Last return value from the callback function + var last_r: isize = 0; + while (it.next()) |entry| { + var dlpi_phdr: [*]elf.Phdr = undefined; + var dlpi_phnum: u16 = undefined; + + if (entry.l_addr != 0) { + const elf_header = @intToPtr(*elf.Ehdr, entry.l_addr); + dlpi_phdr = @intToPtr([*]elf.Phdr, entry.l_addr + elf_header.e_phoff); + dlpi_phnum = elf_header.e_phnum; + } else { + // This is the running ELF image + dlpi_phdr = @intToPtr([*]elf.Phdr, elf_base + ehdr.e_phoff); + dlpi_phnum = ehdr.e_phnum; + } + + var info = dl_phdr_info{ + .dlpi_addr = entry.l_addr, + .dlpi_name = entry.l_name, + .dlpi_phdr = dlpi_phdr, + .dlpi_phnum = dlpi_phnum, + }; + + last_r = callback(&info, @sizeOf(dl_phdr_info), data); + if (last_r != 0) break; + } + + return last_r; +} + pub const ClockGetTimeError = error{ UnsupportedClock, Unexpected, |
