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 standard library.
std › os › linux › vdso › lookup Public Function lookup Doc Source Public Function std.os.linux.vdso.lookup
pub fn lookup (vername : []const u8 , name : []const u8 ) usize Params vername : []const u8 name : []const u8 File os/linux/vdso.zig: 7
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 pub fn lookup (vername : []const u8 , name : []const u8 ) usize {
const vdso_addr = linux .getauxval (std .elf .AT_SYSINFO_EHDR );
if (vdso_addr == 0 ) return 0 ;
const eh = @as (*elf .Ehdr , @ptrFromInt (vdso_addr ));
var ph_addr : usize = vdso_addr + eh .e_phoff ;
var maybe_dynv : ?[*]usize = null ;
var base : usize = maxInt (usize );
{
var i : usize = 0 ;
while (i < eh .e_phnum ) : ({
i += 1 ;
ph_addr += eh .e_phentsize ;
}) {
const this_ph = @as (*elf .ElfN .Phdr , @ptrFromInt (ph_addr ));
switch (this_ph .type ) {
// On WSL1 as well as older kernels, the VDSO ELF image is pre-linked in the upper half
// of the memory space (e.g. vaddr = 0xffffffffff700000 on WSL1).
// Wrapping operations are used on this line as well as subsequent calculations relative to base
// (lines 47, 78) to ensure no overflow check is tripped.
.LOAD => base = vdso_addr +% this_ph .offset -% this_ph .vaddr ,
.DYNAMIC => maybe_dynv = @as ([*]usize , @ptrFromInt (vdso_addr + this_ph .offset )),
else => {},
}
}
}
const dynv = maybe_dynv orelse return 0 ;
if (base == maxInt (usize )) return 0 ;
var maybe_strings : ?[*:0 ]u8 = null ;
var maybe_syms : ?[*]elf .Sym = null ;
var maybe_hashtab : ?[*]linux .Elf_Symndx = null ;
var maybe_versym : ?[*]elf .Versym = null ;
var maybe_verdef : ?*elf .Verdef = null ;
{
var i : usize = 0 ;
while (dynv [i ] != 0 ) : (i += 2 ) {
const p = base +% dynv [i + 1 ];
switch (dynv [i ]) {
elf .DT_STRTAB => maybe_strings = @ptrFromInt (p ),
elf .DT_SYMTAB => maybe_syms = @ptrFromInt (p ),
elf .DT_HASH => maybe_hashtab = @ptrFromInt (p ),
elf .DT_VERSYM => maybe_versym = @ptrFromInt (p ),
elf .DT_VERDEF => maybe_verdef = @ptrFromInt (p ),
else => {},
}
}
}
const strings = maybe_strings orelse return 0 ;
const syms = maybe_syms orelse return 0 ;
const hashtab = maybe_hashtab orelse return 0 ;
if (maybe_verdef == null ) maybe_versym = null ;
const OK_TYPES = (1 << elf .STT_NOTYPE | 1 << elf .STT_OBJECT | 1 << elf .STT_FUNC | 1 << elf .STT_COMMON );
const OK_BINDS = (1 << elf .STB_GLOBAL | 1 << elf .STB_WEAK | 1 << elf .STB_GNU_UNIQUE );
var i : usize = 0 ;
while (i < hashtab [1 ]) : (i += 1 ) {
if (0 == (@as (u32 , 1 ) << @as (u5 , @intCast (syms [i ].st_info & 0xf )) & OK_TYPES )) continue ;
if (0 == (@as (u32 , 1 ) << @as (u5 , @intCast (syms [i ].st_info >> 4 )) & OK_BINDS )) continue ;
if (0 == syms [i ].st_shndx ) continue ;
const sym_name = @as ([*:0 ]u8 , @ptrCast (strings + syms [i ].st_name ));
if (!mem .eql (u8 , name , mem .sliceTo (sym_name , 0 ))) continue ;
if (maybe_versym ) |versym | {
if (!checkver (maybe_verdef .?, versym [i ], vername , strings ))
continue ;
}
return base +% syms [i ].st_value ;
}
return 0 ;
}