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.

DlIterContext

Elf.DlIterContext
const DlIterContext = struct

File

Code

const DlIterContext = struct {
    si: *SelfInfo,
    gpa: Allocator,

    fn callback(info: *std.posix.dl_phdr_info, size: usize, context: *@This()) !void {
        _ = size;

        var build_id: ?[]const u8 = null;
        var gnu_eh_frame: ?[]const u8 = null;

        // Populate `build_id` and `gnu_eh_frame`
        for (info.phdr[0..info.phnum]) |phdr| {
            switch (phdr.type) {
                .NOTE => {
                    // Look for .note.gnu.build-id
                    const segment_ptr: [*]const u8 = @ptrFromInt(info.addr + phdr.vaddr);
                    var r: std.Io.Reader = .fixed(segment_ptr[0..phdr.memsz]);
                    const name_size = r.takeInt(u32, native_endian) catch continue;
                    const desc_size = r.takeInt(u32, native_endian) catch continue;
                    const note_type = r.takeInt(u32, native_endian) catch continue;
                    const name = r.take(name_size) catch continue;
                    if (note_type != std.elf.NT_GNU_BUILD_ID) continue;
                    if (!std.mem.eql(u8, name, "GNU\x00")) continue;
                    const desc = r.take(desc_size) catch continue;
                    build_id = desc;
                },
                std.elf.PT.GNU_EH_FRAME => {
                    const segment_ptr: [*]const u8 = @ptrFromInt(info.addr + phdr.vaddr);
                    gnu_eh_frame = segment_ptr[0..phdr.memsz];
                },
                else => {},
            }
        }

        const gpa = context.gpa;
        const si = context.si;

        const module_index = si.modules.items.len;
        try si.modules.append(gpa, .{
            .load_offset = info.addr,
            // Android libc uses NULL instead of "" to mark the main program
            .name = std.mem.sliceTo(info.name, 0) orelse "",
            .build_id = build_id,
            .gnu_eh_frame = gnu_eh_frame,
            .unwind = null,
            .loaded_elf = null,
        });

        for (info.phdr[0..info.phnum]) |phdr| {
            if (phdr.type != .LOAD) continue;
            try context.si.ranges.append(gpa, .{
                // Overflowing addition handles VSDOs having p_vaddr = 0xffffffffff700000
                .start = info.addr +% phdr.vaddr,
                .len = phdr.memsz,
                .module_index = module_index,
            });
        }
    }
}