feature. See also
. The project being documented here (as the example) is the Zig library itself.
tls.computeAreaDesc
fn computeAreaDesc(phdrs: []elf.Phdr) void
File
Code
fn computeAreaDesc(phdrs: []elf.Phdr) void {
@setRuntimeSafety(false);
@disableInstrumentation();
var tls_phdr: ?*elf.Phdr = null;
var img_base: usize = 0;
for (phdrs) |*phdr| {
switch (phdr.p_type) {
elf.PT_PHDR => img_base = @intFromPtr(phdrs.ptr) - phdr.p_vaddr,
elf.PT_TLS => tls_phdr = phdr,
else => {},
}
}
var align_factor: usize = undefined;
var block_init: []const u8 = undefined;
var block_size: usize = undefined;
if (tls_phdr) |phdr| {
align_factor = phdr.p_align;
// in the `PT_TLS` segment is `p_filesz` and may be less than the former.
block_init = @as([*]u8, @ptrFromInt(img_base + phdr.p_vaddr))[0..phdr.p_filesz];
block_size = phdr.p_memsz;
} else {
align_factor = @alignOf(usize);
block_init = &[_]u8{};
block_size = 0;
}
var dtv_offset: usize = undefined;
var abi_tcb_offset: usize = undefined;
var block_offset: usize = undefined;
// offsets calculated here assume a well-aligned base address.
const area_size = switch (current_variant) {
.I_original => blk: {
var l: usize = 0;
dtv_offset = l;
l += @sizeOf(Dtv);
// and the `ZigTcb` structure can be found by simply subtracting `@sizeOf(ZigTcb)` from
// the TP.
const delta = (l + @sizeOf(ZigTcb)) & (align_factor - 1);
if (delta > 0)
l += align_factor - delta;
l += @sizeOf(ZigTcb);
abi_tcb_offset = l;
l += alignForward(@sizeOf(AbiTcb), align_factor);
block_offset = l;
l += block_size;
break :blk l;
},
.I_modified => blk: {
var l: usize = 0;
dtv_offset = l;
l += @sizeOf(Dtv);
// with the TP pointing to the beginning of the TLS blocks. Add padding so that the TP
// (`abi_tcb_offset`) is aligned to `align_factor` and the `ZigTcb` structure can be
// found by subtracting `@sizeOf(AbiTcb) + @sizeOf(ZigTcb)` from the TP.
const delta = (l + @sizeOf(ZigTcb) + @sizeOf(AbiTcb)) & (align_factor - 1);
if (delta > 0)
l += align_factor - delta;
l += @sizeOf(ZigTcb);
abi_tcb_offset = l;
l += @sizeOf(AbiTcb);
block_offset = l;
l += block_size;
break :blk l;
},
.II => blk: {
var l: usize = 0;
block_offset = l;
l += alignForward(block_size, align_factor);
abi_tcb_offset = l;
l += @sizeOf(AbiTcb);
// can be easily found.
l += @sizeOf(ZigTcb);
l = alignForward(l, @alignOf(Dtv));
dtv_offset = l;
l += @sizeOf(Dtv);
break :blk l;
},
};
area_desc = .{
.size = area_size,
.alignment = align_factor,
.dtv = .{
.offset = dtv_offset,
},
.abi_tcb = .{
.offset = abi_tcb_offset,
},
.block = .{
.init = block_init,
.offset = block_offset,
.size = block_size,
},
.gdt_entry_number = @as(usize, @bitCast(@as(isize, -1))),
};
}