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.

glibcVerFromSoFile

system.glibcVerFromSoFile
fn glibcVerFromSoFile(file_reader: *Io.File.Reader) !std.SemanticVersion

File

lib/std/zig/system.zig:888

Code

fn glibcVerFromSoFile(file_reader: *Io.File.Reader) !std.SemanticVersion {
    const header = try elf.Header.read(&file_reader.interface);
    const str_section_off = header.shoff + @as(u64, header.shentsize) * @as(u64, header.shstrndx);
    try file_reader.seekTo(str_section_off);
    const shstr = try elf.takeSectionHeader(&file_reader.interface, header.is_64, header.endian);
    var strtab_buf: [4096]u8 = undefined;
    const shstrtab = strtab_buf[0..@min(shstr.sh_size, strtab_buf.len)];
    try file_reader.seekTo(shstr.sh_offset);
    try file_reader.interface.readSliceAll(shstrtab);
    const dynstr: struct { offset: u64, size: u64 } = find_dyn_str: {
        var it = header.iterateSectionHeaders(file_reader);
        while (try it.next()) |shdr| {
            const end = mem.findScalarPos(u8, shstrtab, shdr.sh_name, 0) orelse continue;
            const sh_name = shstrtab[shdr.sh_name..end :0];
            if (mem.eql(u8, sh_name, ".dynstr")) break :find_dyn_str .{
                .offset = shdr.sh_offset,
                .size = shdr.sh_size,
            };
        } else return error.InvalidGnuLibCVersion;
    };

    // Here we loop over all the strings in the dynstr string table, assuming that any
    // strings that start with "GLIBC_2." indicate the existence of such a glibc version,
    // and furthermore, that the system-installed glibc is at minimum that version.
    var max_ver: std.SemanticVersion = .{ .major = 2, .minor = 2, .patch = 5 };
    var offset: u64 = 0;
    try file_reader.seekTo(dynstr.offset);
    while (offset < dynstr.size) {
        if (file_reader.interface.takeSentinel(0)) |s| {
            if (mem.startsWith(u8, s, "GLIBC_2.")) {
                const chopped = s["GLIBC_".len..];
                const ver = Target.Query.parseVersion(chopped) catch |err| switch (err) {
                    error.Overflow => return error.InvalidGnuLibCVersion,
                    error.InvalidVersion => return error.InvalidGnuLibCVersion,
                };
                switch (ver.order(max_ver)) {
                    .gt => max_ver = ver,
                    .lt, .eq => continue,
                }
            }
            offset += s.len + 1;
        } else |err| switch (err) {
            error.EndOfStream, error.StreamTooLong => break,
            error.ReadFailed => |e| return e,
        }
    }

    return max_ver;
}