Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

dl_iterate_phdr

posix.dl_iterate_phdr
pub fn dl_iterate_phdr(
    context: anytype,
    comptime Error: type,
    comptime callback: fn (info: *dl_phdr_info, size: usize, context: @TypeOf(context)) Error!void,
) Error!void

File

lib/std/posix.zig:783

Code

pub fn dl_iterate_phdr(
    context: anytype,
    comptime Error: type,
    comptime callback: fn (info: *dl_phdr_info, size: usize, context: @TypeOf(context)) Error!void,
) Error!void {
    const Context = @TypeOf(context);
    const elf = std.elf;
    const dl = @import("dynamic_library.zig");

    switch (builtin.object_format) {
        .elf, .c => {},
        else => @compileError("dl_iterate_phdr is not available for this target"),
    }

    if (builtin.link_libc) {
        switch (system.dl_iterate_phdr(struct {
            fn callbackC(info: *dl_phdr_info, size: usize, data: ?*anyopaque) callconv(.c) c_int {
                const context_ptr: *const Context = @ptrCast(@alignCast(data));
                callback(info, size, context_ptr.*) catch |err| return @intFromError(err);
                return 0;
            }
        }.callbackC, @ptrCast(@constCast(&context)))) {
            0 => return,
            else => |err| return @as(Error, @errorCast(@errorFromInt(@as(@Int(.unsigned, @bitSizeOf(anyerror)), @intCast(err))))),
        }
    }

    var it = dl.linkmap_iterator() catch unreachable;

    // The executable has no dynamic link segment, create a single entry for
    // the whole ELF image.
    if (it.end()) {
        const getauxval = if (builtin.link_libc) std.c.getauxval else std.os.linux.getauxval;
        const phdrs = getSelfPhdrs();
        var info: dl_phdr_info = .{
            .addr = for (phdrs) |phdr| switch (phdr.type) {
                .PHDR => break @intFromPtr(phdrs.ptr) - phdr.vaddr,
                else => {},
            } else unreachable,
            .name = switch (getauxval(std.elf.AT_EXECFN)) {
                0 => "/proc/self/exe",
                else => |name| @ptrFromInt(name),
            },
            .phdr = phdrs.ptr,
            .phnum = @intCast(phdrs.len),
        };

        return callback(&info, @sizeOf(dl_phdr_info), context);
    }

    // Last return value from the callback function.
    while (it.next()) |entry| {
        const phdrs: []elf.ElfN.Phdr = if (entry.addr != 0) phdrs: {
            const ehdr: *elf.ElfN.Ehdr = @ptrFromInt(entry.addr);
            assert(mem.eql(u8, &ehdr.ident.magic, elf.MAGIC));
            const phdrs: [*]elf.ElfN.Phdr = @ptrFromInt(entry.addr + ehdr.phoff);
            break :phdrs phdrs[0..ehdr.phnum];
        } else getSelfPhdrs();

        var info: dl_phdr_info = .{
            .addr = entry.addr,
            .name = entry.name,
            .phdr = phdrs.ptr,
            .phnum = @intCast(phdrs.len),
        };

        try callback(&info, @sizeOf(dl_phdr_info), context);
    }
}