| author | |
| committer | |
| log | 25198810c88d474c63ff537e3647f12e7df6297c |
| tree | f92e3b6dcf75aa653df9786fb6c17360291a8e4c |
| parent | 7930efc60becd7624471419b8fd49800512d4e10 |
This is needed to ensure that start code does not try to access thread
local storage before it has set up thread local storage.8 files changed, 72 insertions(+), 15 deletions(-)
lib/std/zig/AstGen.zig+8-6| ... | @@ -2817,6 +2817,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As | ... | @@ -2817,6 +2817,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2817 | 2817 | ||
| 2818 | .extended => switch (gz.astgen.instructions.items(.data)[@intFromEnum(inst)].extended.opcode) { | 2818 | .extended => switch (gz.astgen.instructions.items(.data)[@intFromEnum(inst)].extended.opcode) { |
| 2819 | .breakpoint, | 2819 | .breakpoint, |
| 2820 | .disable_instrumentation, | ||
| 2820 | .fence, | 2821 | .fence, |
| 2821 | .set_float_mode, | 2822 | .set_float_mode, |
| 2822 | .set_align_stack, | 2823 | .set_align_stack, |
| ... | @@ -9305,12 +9306,13 @@ fn builtinCall( | ... | @@ -9305,12 +9306,13 @@ fn builtinCall( |
| 9305 | }, | 9306 | }, |
| 9306 | 9307 | ||
| 9307 | // zig fmt: off | 9308 | // zig fmt: off |
| 9308 | .This => return rvalue(gz, ri, try gz.addNodeExtended(.this, node), node), | 9309 | .This => return rvalue(gz, ri, try gz.addNodeExtended(.this, node), node), |
| 9309 | .return_address => return rvalue(gz, ri, try gz.addNodeExtended(.ret_addr, node), node), | 9310 | .return_address => return rvalue(gz, ri, try gz.addNodeExtended(.ret_addr, node), node), |
| 9310 | .error_return_trace => return rvalue(gz, ri, try gz.addNodeExtended(.error_return_trace, node), node), | 9311 | .error_return_trace => return rvalue(gz, ri, try gz.addNodeExtended(.error_return_trace, node), node), |
| 9311 | .frame => return rvalue(gz, ri, try gz.addNodeExtended(.frame, node), node), | 9312 | .frame => return rvalue(gz, ri, try gz.addNodeExtended(.frame, node), node), |
| 9312 | .frame_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, node), node), | 9313 | .frame_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, node), node), |
| 9313 | .breakpoint => return rvalue(gz, ri, try gz.addNodeExtended(.breakpoint, node), node), | 9314 | .breakpoint => return rvalue(gz, ri, try gz.addNodeExtended(.breakpoint, node), node), |
| 9315 | .disable_instrumentation => return rvalue(gz, ri, try gz.addNodeExtended(.disable_instrumentation, node), node), | ||
| 9314 | 9316 | ||
| 9315 | .type_info => return simpleUnOpType(gz, scope, ri, node, params[0], .type_info), | 9317 | .type_info => return simpleUnOpType(gz, scope, ri, node, params[0], .type_info), |
| 9316 | .size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .size_of), | 9318 | .size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .size_of), |
lib/std/zig/AstRlAnnotate.zig+1| ... | @@ -877,6 +877,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. | ... | @@ -877,6 +877,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. |
| 877 | .error_return_trace, | 877 | .error_return_trace, |
| 878 | .frame, | 878 | .frame, |
| 879 | .breakpoint, | 879 | .breakpoint, |
| 880 | .disable_instrumentation, | ||
| 880 | .in_comptime, | 881 | .in_comptime, |
| 881 | .panic, | 882 | .panic, |
| 882 | .trap, | 883 | .trap, |
lib/std/zig/BuiltinFn.zig+9| ... | @@ -15,6 +15,7 @@ pub const Tag = enum { | ... | @@ -15,6 +15,7 @@ pub const Tag = enum { |
| 15 | int_from_bool, | 15 | int_from_bool, |
| 16 | bit_size_of, | 16 | bit_size_of, |
| 17 | breakpoint, | 17 | breakpoint, |
| 18 | disable_instrumentation, | ||
| 18 | mul_add, | 19 | mul_add, |
| 19 | byte_swap, | 20 | byte_swap, |
| 20 | bit_reverse, | 21 | bit_reverse, |
| ... | @@ -263,6 +264,14 @@ pub const list = list: { | ... | @@ -263,6 +264,14 @@ pub const list = list: { |
| 263 | .illegal_outside_function = true, | 264 | .illegal_outside_function = true, |
| 264 | }, | 265 | }, |
| 265 | }, | 266 | }, |
| 267 | .{ | ||
| 268 | "@disableInstrumentation", | ||
| 269 | .{ | ||
| 270 | .tag = .disable_instrumentation, | ||
| 271 | .param_count = 0, | ||
| 272 | .illegal_outside_function = true, | ||
| 273 | }, | ||
| 274 | }, | ||
| 266 | .{ | 275 | .{ |
| 267 | "@mulAdd", | 276 | "@mulAdd", |
| 268 | .{ | 277 | .{ |
lib/std/zig/Zir.zig+3-1| ... | @@ -1553,7 +1553,7 @@ pub const Inst = struct { | ... | @@ -1553,7 +1553,7 @@ pub const Inst = struct { |
| 1553 | => false, | 1553 | => false, |
| 1554 | 1554 | ||
| 1555 | .extended => switch (data.extended.opcode) { | 1555 | .extended => switch (data.extended.opcode) { |
| 1556 | .fence, .set_cold, .breakpoint => true, | 1556 | .fence, .set_cold, .breakpoint, .disable_instrumentation => true, |
| 1557 | else => false, | 1557 | else => false, |
| 1558 | }, | 1558 | }, |
| 1559 | }; | 1559 | }; |
| ... | @@ -1973,6 +1973,8 @@ pub const Inst = struct { | ... | @@ -1973,6 +1973,8 @@ pub const Inst = struct { |
| 1973 | /// Implements `@breakpoint`. | 1973 | /// Implements `@breakpoint`. |
| 1974 | /// `operand` is `src_node: i32`. | 1974 | /// `operand` is `src_node: i32`. |
| 1975 | breakpoint, | 1975 | breakpoint, |
| 1976 | /// Implement builtin `@disableInstrumentation`. `operand` is `src_node: i32`. | ||
| 1977 | disable_instrumentation, | ||
| 1976 | /// Implements the `@select` builtin. | 1978 | /// Implements the `@select` builtin. |
| 1977 | /// `operand` is payload index to `Select`. | 1979 | /// `operand` is payload index to `Select`. |
| 1978 | select, | 1980 | select, |
src/InternPool.zig+18-2| ... | @@ -5184,11 +5184,11 @@ pub const FuncAnalysis = packed struct(u32) { | ... | @@ -5184,11 +5184,11 @@ pub const FuncAnalysis = packed struct(u32) { |
| 5184 | is_noinline: bool, | 5184 | is_noinline: bool, |
| 5185 | calls_or_awaits_errorable_fn: bool, | 5185 | calls_or_awaits_errorable_fn: bool, |
| 5186 | stack_alignment: Alignment, | 5186 | stack_alignment: Alignment, |
| 5187 | |||
| 5188 | /// True if this function has an inferred error set. | 5187 | /// True if this function has an inferred error set. |
| 5189 | inferred_error_set: bool, | 5188 | inferred_error_set: bool, |
| 5189 | disable_instrumentation: bool, | ||
| 5190 | 5190 | ||
| 5191 | _: u14 = 0, | 5191 | _: u13 = 0, |
| 5192 | 5192 | ||
| 5193 | pub const State = enum(u8) { | 5193 | pub const State = enum(u8) { |
| 5194 | /// This function has not yet undergone analysis, because we have not | 5194 | /// This function has not yet undergone analysis, because we have not |
| ... | @@ -8111,6 +8111,7 @@ pub fn getFuncDecl( | ... | @@ -8111,6 +8111,7 @@ pub fn getFuncDecl( |
| 8111 | .calls_or_awaits_errorable_fn = false, | 8111 | .calls_or_awaits_errorable_fn = false, |
| 8112 | .stack_alignment = .none, | 8112 | .stack_alignment = .none, |
| 8113 | .inferred_error_set = false, | 8113 | .inferred_error_set = false, |
| 8114 | .disable_instrumentation = false, | ||
| 8114 | }, | 8115 | }, |
| 8115 | .owner_decl = key.owner_decl, | 8116 | .owner_decl = key.owner_decl, |
| 8116 | .ty = key.ty, | 8117 | .ty = key.ty, |
| ... | @@ -8214,6 +8215,7 @@ pub fn getFuncDeclIes( | ... | @@ -8214,6 +8215,7 @@ pub fn getFuncDeclIes( |
| 8214 | .calls_or_awaits_errorable_fn = false, | 8215 | .calls_or_awaits_errorable_fn = false, |
| 8215 | .stack_alignment = .none, | 8216 | .stack_alignment = .none, |
| 8216 | .inferred_error_set = true, | 8217 | .inferred_error_set = true, |
| 8218 | .disable_instrumentation = false, | ||
| 8217 | }, | 8219 | }, |
| 8218 | .owner_decl = key.owner_decl, | 8220 | .owner_decl = key.owner_decl, |
| 8219 | .ty = func_ty, | 8221 | .ty = func_ty, |
| ... | @@ -8405,6 +8407,7 @@ pub fn getFuncInstance( | ... | @@ -8405,6 +8407,7 @@ pub fn getFuncInstance( |
| 8405 | .calls_or_awaits_errorable_fn = false, | 8407 | .calls_or_awaits_errorable_fn = false, |
| 8406 | .stack_alignment = .none, | 8408 | .stack_alignment = .none, |
| 8407 | .inferred_error_set = false, | 8409 | .inferred_error_set = false, |
| 8410 | .disable_instrumentation = false, | ||
| 8408 | }, | 8411 | }, |
| 8409 | // This is populated after we create the Decl below. It is not read | 8412 | // This is populated after we create the Decl below. It is not read |
| 8410 | // by equality or hashing functions. | 8413 | // by equality or hashing functions. |
| ... | @@ -8504,6 +8507,7 @@ pub fn getFuncInstanceIes( | ... | @@ -8504,6 +8507,7 @@ pub fn getFuncInstanceIes( |
| 8504 | .calls_or_awaits_errorable_fn = false, | 8507 | .calls_or_awaits_errorable_fn = false, |
| 8505 | .stack_alignment = .none, | 8508 | .stack_alignment = .none, |
| 8506 | .inferred_error_set = true, | 8509 | .inferred_error_set = true, |
| 8510 | .disable_instrumentation = false, | ||
| 8507 | }, | 8511 | }, |
| 8508 | // This is populated after we create the Decl below. It is not read | 8512 | // This is populated after we create the Decl below. It is not read |
| 8509 | // by equality or hashing functions. | 8513 | // by equality or hashing functions. |
| ... | @@ -11225,6 +11229,18 @@ pub fn funcSetCallsOrAwaitsErrorableFn(ip: *InternPool, func: Index) void { | ... | @@ -11225,6 +11229,18 @@ pub fn funcSetCallsOrAwaitsErrorableFn(ip: *InternPool, func: Index) void { |
| 11225 | @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); | 11229 | @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); |
| 11226 | } | 11230 | } |
| 11227 | 11231 | ||
| 11232 | pub fn funcSetDisableInstrumentation(ip: *InternPool, func: Index) void { | ||
| 11233 | const unwrapped_func = func.unwrap(ip); | ||
| 11234 | const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex; | ||
| 11235 | extra_mutex.lock(); | ||
| 11236 | defer extra_mutex.unlock(); | ||
| 11237 | |||
| 11238 | const analysis_ptr = ip.funcAnalysisPtr(func); | ||
| 11239 | var analysis = analysis_ptr.*; | ||
| 11240 | analysis.disable_instrumentation = true; | ||
| 11241 | @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); | ||
| 11242 | } | ||
| 11243 | |||
| 11228 | pub fn funcSetCold(ip: *InternPool, func: Index, is_cold: bool) void { | 11244 | pub fn funcSetCold(ip: *InternPool, func: Index, is_cold: bool) void { |
| 11229 | const unwrapped_func = func.unwrap(ip); | 11245 | const unwrapped_func = func.unwrap(ip); |
| 11230 | const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex; | 11246 | const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex; |
src/Sema.zig+13| ... | @@ -1316,6 +1316,11 @@ fn analyzeBodyInner( | ... | @@ -1316,6 +1316,11 @@ fn analyzeBodyInner( |
| 1316 | i += 1; | 1316 | i += 1; |
| 1317 | continue; | 1317 | continue; |
| 1318 | }, | 1318 | }, |
| 1319 | .disable_instrumentation => { | ||
| 1320 | try sema.zirDisableInstrumentation(); | ||
| 1321 | i += 1; | ||
| 1322 | continue; | ||
| 1323 | }, | ||
| 1319 | .restore_err_ret_index => { | 1324 | .restore_err_ret_index => { |
| 1320 | try sema.zirRestoreErrRetIndex(block, extended); | 1325 | try sema.zirRestoreErrRetIndex(block, extended); |
| 1321 | i += 1; | 1326 | i += 1; |
| ... | @@ -6576,6 +6581,14 @@ fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) | ... | @@ -6576,6 +6581,14 @@ fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) |
| 6576 | ip.funcSetCold(sema.func_index, is_cold); | 6581 | ip.funcSetCold(sema.func_index, is_cold); |
| 6577 | } | 6582 | } |
| 6578 | 6583 | ||
| 6584 | fn zirDisableInstrumentation(sema: *Sema) CompileError!void { | ||
| 6585 | const pt = sema.pt; | ||
| 6586 | const mod = pt.zcu; | ||
| 6587 | const ip = &mod.intern_pool; | ||
| 6588 | if (sema.func_index == .none) return; // does nothing outside a function | ||
| 6589 | ip.funcSetDisableInstrumentation(sema.func_index); | ||
| 6590 | } | ||
| 6591 | |||
| 6579 | fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { | 6592 | fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { |
| 6580 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; | 6593 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 6581 | const src = block.builtinCallArgSrc(extra.node, 0); | 6594 | const src = block.builtinCallArgSrc(extra.node, 0); |
src/codegen/llvm.zig+19-6| ... | @@ -1383,6 +1383,25 @@ pub const Object = struct { | ... | @@ -1383,6 +1383,25 @@ pub const Object = struct { |
| 1383 | _ = try attributes.removeFnAttr(.cold); | 1383 | _ = try attributes.removeFnAttr(.cold); |
| 1384 | } | 1384 | } |
| 1385 | 1385 | ||
| 1386 | if (owner_mod.sanitize_thread and !func_analysis.disable_instrumentation) { | ||
| 1387 | try attributes.addFnAttr(.sanitize_thread, &o.builder); | ||
| 1388 | } else { | ||
| 1389 | _ = try attributes.removeFnAttr(.sanitize_thread); | ||
| 1390 | } | ||
| 1391 | if (owner_mod.fuzz and !func_analysis.disable_instrumentation) { | ||
| 1392 | try attributes.addFnAttr(.optforfuzzing, &o.builder); | ||
| 1393 | if (comp.config.any_fuzz) { | ||
| 1394 | _ = try attributes.removeFnAttr(.skipprofile); | ||
| 1395 | _ = try attributes.removeFnAttr(.nosanitize_coverage); | ||
| 1396 | } | ||
| 1397 | } else { | ||
| 1398 | _ = try attributes.removeFnAttr(.optforfuzzing); | ||
| 1399 | if (comp.config.any_fuzz) { | ||
| 1400 | try attributes.addFnAttr(.skipprofile, &o.builder); | ||
| 1401 | try attributes.addFnAttr(.nosanitize_coverage, &o.builder); | ||
| 1402 | } | ||
| 1403 | } | ||
| 1404 | |||
| 1386 | // TODO: disable this if safety is off for the function scope | 1405 | // TODO: disable this if safety is off for the function scope |
| 1387 | const ssp_buf_size = owner_mod.stack_protector; | 1406 | const ssp_buf_size = owner_mod.stack_protector; |
| 1388 | if (ssp_buf_size != 0) { | 1407 | if (ssp_buf_size != 0) { |
| ... | @@ -2982,12 +3001,6 @@ pub const Object = struct { | ... | @@ -2982,12 +3001,6 @@ pub const Object = struct { |
| 2982 | try attributes.addFnAttr(.minsize, &o.builder); | 3001 | try attributes.addFnAttr(.minsize, &o.builder); |
| 2983 | try attributes.addFnAttr(.optsize, &o.builder); | 3002 | try attributes.addFnAttr(.optsize, &o.builder); |
| 2984 | } | 3003 | } |
| 2985 | if (owner_mod.sanitize_thread) { | ||
| 2986 | try attributes.addFnAttr(.sanitize_thread, &o.builder); | ||
| 2987 | } | ||
| 2988 | if (owner_mod.fuzz) { | ||
| 2989 | try attributes.addFnAttr(.optforfuzzing, &o.builder); | ||
| 2990 | } | ||
| 2991 | const target = owner_mod.resolved_target.result; | 3004 | const target = owner_mod.resolved_target.result; |
| 2992 | if (target.cpu.model.llvm_name) |s| { | 3005 | if (target.cpu.model.llvm_name) |s| { |
| 2993 | try attributes.addFnAttr(.{ .string = .{ | 3006 | try attributes.addFnAttr(.{ .string = .{ |
src/print_zir.zig+1| ... | @@ -524,6 +524,7 @@ const Writer = struct { | ... | @@ -524,6 +524,7 @@ const Writer = struct { |
| 524 | .frame, | 524 | .frame, |
| 525 | .frame_address, | 525 | .frame_address, |
| 526 | .breakpoint, | 526 | .breakpoint, |
| 527 | .disable_instrumentation, | ||
| 527 | .c_va_start, | 528 | .c_va_start, |
| 528 | .in_comptime, | 529 | .in_comptime, |
| 529 | .value_placeholder, | 530 | .value_placeholder, |