@@ -110,6 +110,8 @@ const TLSImage = struct {
110
110
pub var tls_image : TLSImage = undefined ;
111
111
112
112
pub fn setThreadPointer (addr : usize ) void {
113
+ @setRuntimeSafety (false );
114
+ @disableInstrumentation ();
113
115
switch (native_arch ) {
114
116
.x86 = > {
115
117
var user_desc : linux.user_desc = .{
@@ -125,7 +127,7 @@ pub fn setThreadPointer(addr: usize) void {
125
127
.useable = 1 ,
126
128
},
127
129
};
128
- const rc = linux .syscall1 ( . set_thread_area , @intFromPtr (& user_desc ));
130
+ const rc = @call ( .always_inline , linux .syscall1 , .{ . set_thread_area , @intFromPtr (& user_desc ) } );
129
131
assert (rc == 0 );
130
132
131
133
const gdt_entry_number = user_desc .entry_number ;
@@ -138,7 +140,7 @@ pub fn setThreadPointer(addr: usize) void {
138
140
);
139
141
},
140
142
.x86_64 = > {
141
- const rc = linux .syscall2 ( . arch_prctl , linux .ARCH .SET_FS , addr );
143
+ const rc = @call ( .always_inline , linux .syscall2 , .{ . arch_prctl , linux .ARCH .SET_FS , addr } );
142
144
assert (rc == 0 );
143
145
},
144
146
.aarch64 , .aarch64_be = > {
@@ -149,7 +151,7 @@ pub fn setThreadPointer(addr: usize) void {
149
151
);
150
152
},
151
153
.arm , .thumb = > {
152
- const rc = linux .syscall1 ( . set_tls , addr );
154
+ const rc = @call ( .always_inline , linux .syscall1 , .{ . set_tls , addr } );
153
155
assert (rc == 0 );
154
156
},
155
157
.riscv64 = > {
@@ -160,7 +162,7 @@ pub fn setThreadPointer(addr: usize) void {
160
162
);
161
163
},
162
164
.mips , .mipsel , .mips64 , .mips64el = > {
163
- const rc = linux .syscall1 ( . set_thread_area , addr );
165
+ const rc = @call ( .always_inline , linux .syscall1 , .{ . set_thread_area , addr } );
164
166
assert (rc == 0 );
165
167
},
166
168
.powerpc , .powerpcle = > {
@@ -189,6 +191,9 @@ pub fn setThreadPointer(addr: usize) void {
189
191
}
190
192
191
193
fn initTLS (phdrs : []elf.Phdr ) void {
194
+ @setRuntimeSafety (false );
195
+ @disableInstrumentation ();
196
+
192
197
var tls_phdr : ? * elf.Phdr = null ;
193
198
var img_base : usize = 0 ;
194
199
@@ -236,22 +241,22 @@ fn initTLS(phdrs: []elf.Phdr) void {
236
241
l += tls_align_factor - delta ;
237
242
l += @sizeOf (CustomData );
238
243
tcb_offset = l ;
239
- l += mem . alignForward (usize , tls_tcb_size , tls_align_factor );
244
+ l += alignForward (tls_tcb_size , tls_align_factor );
240
245
data_offset = l ;
241
246
l += tls_data_alloc_size ;
242
247
break :blk l ;
243
248
},
244
249
.VariantII = > blk : {
245
250
var l : usize = 0 ;
246
251
data_offset = l ;
247
- l += mem . alignForward (usize , tls_data_alloc_size , tls_align_factor );
252
+ l += alignForward (tls_data_alloc_size , tls_align_factor );
248
253
// The thread pointer is aligned to p_align
249
254
tcb_offset = l ;
250
255
l += tls_tcb_size ;
251
256
// The CustomData structure is right after the TCB with no padding
252
257
// in between so it can be easily found
253
258
l += @sizeOf (CustomData );
254
- l = mem . alignForward (usize , l , @alignOf (DTV ));
259
+ l = alignForward (l , @alignOf (DTV ));
255
260
dtv_offset = l ;
256
261
l += @sizeOf (DTV );
257
262
break :blk l ;
@@ -270,13 +275,28 @@ fn initTLS(phdrs: []elf.Phdr) void {
270
275
};
271
276
}
272
277
278
+ /// Inline because TLS is not set up yet.
279
+ inline fn alignForward (addr : usize , alignment : usize ) usize {
280
+ return alignBackward (addr + (alignment - 1 ), alignment );
281
+ }
282
+
283
+ /// Inline because TLS is not set up yet.
284
+ inline fn alignBackward (addr : usize , alignment : usize ) usize {
285
+ return addr & ~ (alignment - 1 );
286
+ }
287
+
288
+ /// Inline because TLS is not set up yet.
273
289
inline fn alignPtrCast (comptime T : type , ptr : [* ]u8 ) * T {
274
290
return @ptrCast (@alignCast (ptr ));
275
291
}
276
292
277
293
/// Initializes all the fields of the static TLS area and returns the computed
278
294
/// architecture-specific value of the thread-pointer register
295
+ ///
296
+ /// This function is inline because thread local storage is not set up yet.
279
297
pub fn prepareTLS (area : []u8 ) usize {
298
+ @setRuntimeSafety (false );
299
+ @disableInstrumentation ();
280
300
// Clear the area we're going to use, just to be safe
281
301
@memset (area , 0 );
282
302
// Prepare the DTV
@@ -310,6 +330,9 @@ pub fn prepareTLS(area: []u8) usize {
310
330
var main_thread_tls_buffer : [0x2100 ]u8 align (mem .page_size ) = undefined ;
311
331
312
332
pub fn initStaticTLS (phdrs : []elf.Phdr ) void {
333
+ @setRuntimeSafety (false );
334
+ @disableInstrumentation ();
335
+
313
336
initTLS (phdrs );
314
337
315
338
const tls_area = blk : {
@@ -321,22 +344,47 @@ pub fn initStaticTLS(phdrs: []elf.Phdr) void {
321
344
break :blk main_thread_tls_buffer [0.. tls_image .alloc_size ];
322
345
}
323
346
324
- const alloc_tls_area = posix . mmap (
347
+ const begin_addr = mmap (
325
348
null ,
326
349
tls_image .alloc_size + tls_image .alloc_align - 1 ,
327
350
posix .PROT .READ | posix .PROT .WRITE ,
328
351
.{ .TYPE = .PRIVATE , .ANONYMOUS = true },
329
352
-1 ,
330
353
0 ,
331
- ) catch posix .abort ();
354
+ );
355
+ if (@as (isize , @bitCast (begin_addr )) < 0 ) @trap ();
356
+ const alloc_tls_area : [* ]align (mem .page_size ) u8 = @ptrFromInt (begin_addr );
332
357
333
358
// Make sure the slice is correctly aligned.
334
- const begin_addr = @intFromPtr (alloc_tls_area .ptr );
335
- const begin_aligned_addr = mem .alignForward (usize , begin_addr , tls_image .alloc_align );
359
+ const begin_aligned_addr = alignForward (begin_addr , tls_image .alloc_align );
336
360
const start = begin_aligned_addr - begin_addr ;
337
- break :blk alloc_tls_area [start .. start + tls_image .alloc_size ];
361
+ break :blk alloc_tls_area [start .. ][0 .. tls_image .alloc_size ];
338
362
};
339
363
340
364
const tp_value = prepareTLS (tls_area );
341
365
setThreadPointer (tp_value );
342
366
}
367
+
368
+ inline fn mmap (address : ? [* ]u8 , length : usize , prot : usize , flags : linux.MAP , fd : i32 , offset : i64 ) usize {
369
+ if (@hasField (linux .SYS , "mmap2" )) {
370
+ return @call (.always_inline , linux .syscall6 , .{
371
+ .mmap2 ,
372
+ @intFromPtr (address ),
373
+ length ,
374
+ prot ,
375
+ @as (u32 , @bitCast (flags )),
376
+ @as (usize , @bitCast (@as (isize , fd ))),
377
+ @as (usize , @truncate (@as (u64 , @bitCast (offset )) / linux .MMAP2_UNIT )),
378
+ });
379
+ } else {
380
+ return @call (.always_inline , linux .syscall6 , .{
381
+ .mmap ,
382
+ @intFromPtr (address ),
383
+ length ,
384
+ prot ,
385
+ @as (u32 , @bitCast (flags )),
386
+ @as (usize , @bitCast (@as (isize , fd ))),
387
+ @as (u64 , @bitCast (offset )),
388
+ });
389
+ }
390
+ }
0 commit comments