feature. See also
. The project being documented here (as the example) is the Zig library itself.
system.glibcVerFromSoFile
fn glibcVerFromSoFile(file_reader: *Io.File.Reader) !std.SemanticVersion
File
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;
};
// 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;
}