aboutsummaryrefslogtreecommitdiff
path: root/std/os.zig
diff options
context:
space:
mode:
authorLemonBoy <thatlemon@gmail.com>2019-05-29 10:30:30 +0200
committerLemonBoy <thatlemon@gmail.com>2019-05-31 11:59:53 +0200
commit46cbed621b287d339a97e77e8e1bfd5090bd247c (patch)
tree6c9a8fd66970d5b898fd13e350faf2ed30e0a6fa /std/os.zig
parent4b30e40a9199accee765e759bbcae133298fa54a (diff)
downloadzig-46cbed621b287d339a97e77e8e1bfd5090bd247c.tar.gz
zig-46cbed621b287d339a97e77e8e1bfd5090bd247c.zip
Move dl_iterate_phdr to os.zig
Diffstat (limited to 'std/os.zig')
-rw-r--r--std/os.zig66
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,