mirror of
https://github.com/ziglang/zig.git
synced 2026-01-19 13:55:20 +00:00
add new builtin: @disableInstrumentation
This is needed to ensure that start code does not try to access thread local storage before it has set up thread local storage.
This commit is contained in:
parent
7930efc60b
commit
25198810c8
@ -2817,6 +2817,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
|
||||
|
||||
.extended => switch (gz.astgen.instructions.items(.data)[@intFromEnum(inst)].extended.opcode) {
|
||||
.breakpoint,
|
||||
.disable_instrumentation,
|
||||
.fence,
|
||||
.set_float_mode,
|
||||
.set_align_stack,
|
||||
@ -9305,12 +9306,13 @@ fn builtinCall(
|
||||
},
|
||||
|
||||
// zig fmt: off
|
||||
.This => return rvalue(gz, ri, try gz.addNodeExtended(.this, node), node),
|
||||
.return_address => return rvalue(gz, ri, try gz.addNodeExtended(.ret_addr, node), node),
|
||||
.error_return_trace => return rvalue(gz, ri, try gz.addNodeExtended(.error_return_trace, node), node),
|
||||
.frame => return rvalue(gz, ri, try gz.addNodeExtended(.frame, node), node),
|
||||
.frame_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, node), node),
|
||||
.breakpoint => return rvalue(gz, ri, try gz.addNodeExtended(.breakpoint, node), node),
|
||||
.This => return rvalue(gz, ri, try gz.addNodeExtended(.this, node), node),
|
||||
.return_address => return rvalue(gz, ri, try gz.addNodeExtended(.ret_addr, node), node),
|
||||
.error_return_trace => return rvalue(gz, ri, try gz.addNodeExtended(.error_return_trace, node), node),
|
||||
.frame => return rvalue(gz, ri, try gz.addNodeExtended(.frame, node), node),
|
||||
.frame_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, node), node),
|
||||
.breakpoint => return rvalue(gz, ri, try gz.addNodeExtended(.breakpoint, node), node),
|
||||
.disable_instrumentation => return rvalue(gz, ri, try gz.addNodeExtended(.disable_instrumentation, node), node),
|
||||
|
||||
.type_info => return simpleUnOpType(gz, scope, ri, node, params[0], .type_info),
|
||||
.size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .size_of),
|
||||
|
||||
@ -877,6 +877,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
|
||||
.error_return_trace,
|
||||
.frame,
|
||||
.breakpoint,
|
||||
.disable_instrumentation,
|
||||
.in_comptime,
|
||||
.panic,
|
||||
.trap,
|
||||
|
||||
@ -15,6 +15,7 @@ pub const Tag = enum {
|
||||
int_from_bool,
|
||||
bit_size_of,
|
||||
breakpoint,
|
||||
disable_instrumentation,
|
||||
mul_add,
|
||||
byte_swap,
|
||||
bit_reverse,
|
||||
@ -263,6 +264,14 @@ pub const list = list: {
|
||||
.illegal_outside_function = true,
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@disableInstrumentation",
|
||||
.{
|
||||
.tag = .disable_instrumentation,
|
||||
.param_count = 0,
|
||||
.illegal_outside_function = true,
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@mulAdd",
|
||||
.{
|
||||
|
||||
@ -1553,7 +1553,7 @@ pub const Inst = struct {
|
||||
=> false,
|
||||
|
||||
.extended => switch (data.extended.opcode) {
|
||||
.fence, .set_cold, .breakpoint => true,
|
||||
.fence, .set_cold, .breakpoint, .disable_instrumentation => true,
|
||||
else => false,
|
||||
},
|
||||
};
|
||||
@ -1973,6 +1973,8 @@ pub const Inst = struct {
|
||||
/// Implements `@breakpoint`.
|
||||
/// `operand` is `src_node: i32`.
|
||||
breakpoint,
|
||||
/// Implement builtin `@disableInstrumentation`. `operand` is `src_node: i32`.
|
||||
disable_instrumentation,
|
||||
/// Implements the `@select` builtin.
|
||||
/// `operand` is payload index to `Select`.
|
||||
select,
|
||||
|
||||
@ -5184,11 +5184,11 @@ pub const FuncAnalysis = packed struct(u32) {
|
||||
is_noinline: bool,
|
||||
calls_or_awaits_errorable_fn: bool,
|
||||
stack_alignment: Alignment,
|
||||
|
||||
/// True if this function has an inferred error set.
|
||||
inferred_error_set: bool,
|
||||
disable_instrumentation: bool,
|
||||
|
||||
_: u14 = 0,
|
||||
_: u13 = 0,
|
||||
|
||||
pub const State = enum(u8) {
|
||||
/// This function has not yet undergone analysis, because we have not
|
||||
@ -8111,6 +8111,7 @@ pub fn getFuncDecl(
|
||||
.calls_or_awaits_errorable_fn = false,
|
||||
.stack_alignment = .none,
|
||||
.inferred_error_set = false,
|
||||
.disable_instrumentation = false,
|
||||
},
|
||||
.owner_decl = key.owner_decl,
|
||||
.ty = key.ty,
|
||||
@ -8214,6 +8215,7 @@ pub fn getFuncDeclIes(
|
||||
.calls_or_awaits_errorable_fn = false,
|
||||
.stack_alignment = .none,
|
||||
.inferred_error_set = true,
|
||||
.disable_instrumentation = false,
|
||||
},
|
||||
.owner_decl = key.owner_decl,
|
||||
.ty = func_ty,
|
||||
@ -8405,6 +8407,7 @@ pub fn getFuncInstance(
|
||||
.calls_or_awaits_errorable_fn = false,
|
||||
.stack_alignment = .none,
|
||||
.inferred_error_set = false,
|
||||
.disable_instrumentation = false,
|
||||
},
|
||||
// This is populated after we create the Decl below. It is not read
|
||||
// by equality or hashing functions.
|
||||
@ -8504,6 +8507,7 @@ pub fn getFuncInstanceIes(
|
||||
.calls_or_awaits_errorable_fn = false,
|
||||
.stack_alignment = .none,
|
||||
.inferred_error_set = true,
|
||||
.disable_instrumentation = false,
|
||||
},
|
||||
// This is populated after we create the Decl below. It is not read
|
||||
// by equality or hashing functions.
|
||||
@ -11225,6 +11229,18 @@ pub fn funcSetCallsOrAwaitsErrorableFn(ip: *InternPool, func: Index) void {
|
||||
@atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
|
||||
}
|
||||
|
||||
pub fn funcSetDisableInstrumentation(ip: *InternPool, func: Index) void {
|
||||
const unwrapped_func = func.unwrap(ip);
|
||||
const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;
|
||||
extra_mutex.lock();
|
||||
defer extra_mutex.unlock();
|
||||
|
||||
const analysis_ptr = ip.funcAnalysisPtr(func);
|
||||
var analysis = analysis_ptr.*;
|
||||
analysis.disable_instrumentation = true;
|
||||
@atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
|
||||
}
|
||||
|
||||
pub fn funcSetCold(ip: *InternPool, func: Index, is_cold: bool) void {
|
||||
const unwrapped_func = func.unwrap(ip);
|
||||
const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;
|
||||
|
||||
13
src/Sema.zig
13
src/Sema.zig
@ -1316,6 +1316,11 @@ fn analyzeBodyInner(
|
||||
i += 1;
|
||||
continue;
|
||||
},
|
||||
.disable_instrumentation => {
|
||||
try sema.zirDisableInstrumentation();
|
||||
i += 1;
|
||||
continue;
|
||||
},
|
||||
.restore_err_ret_index => {
|
||||
try sema.zirRestoreErrRetIndex(block, extended);
|
||||
i += 1;
|
||||
@ -6576,6 +6581,14 @@ fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData)
|
||||
ip.funcSetCold(sema.func_index, is_cold);
|
||||
}
|
||||
|
||||
fn zirDisableInstrumentation(sema: *Sema) CompileError!void {
|
||||
const pt = sema.pt;
|
||||
const mod = pt.zcu;
|
||||
const ip = &mod.intern_pool;
|
||||
if (sema.func_index == .none) return; // does nothing outside a function
|
||||
ip.funcSetDisableInstrumentation(sema.func_index);
|
||||
}
|
||||
|
||||
fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
|
||||
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
|
||||
const src = block.builtinCallArgSrc(extra.node, 0);
|
||||
|
||||
@ -1383,6 +1383,25 @@ pub const Object = struct {
|
||||
_ = try attributes.removeFnAttr(.cold);
|
||||
}
|
||||
|
||||
if (owner_mod.sanitize_thread and !func_analysis.disable_instrumentation) {
|
||||
try attributes.addFnAttr(.sanitize_thread, &o.builder);
|
||||
} else {
|
||||
_ = try attributes.removeFnAttr(.sanitize_thread);
|
||||
}
|
||||
if (owner_mod.fuzz and !func_analysis.disable_instrumentation) {
|
||||
try attributes.addFnAttr(.optforfuzzing, &o.builder);
|
||||
if (comp.config.any_fuzz) {
|
||||
_ = try attributes.removeFnAttr(.skipprofile);
|
||||
_ = try attributes.removeFnAttr(.nosanitize_coverage);
|
||||
}
|
||||
} else {
|
||||
_ = try attributes.removeFnAttr(.optforfuzzing);
|
||||
if (comp.config.any_fuzz) {
|
||||
try attributes.addFnAttr(.skipprofile, &o.builder);
|
||||
try attributes.addFnAttr(.nosanitize_coverage, &o.builder);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: disable this if safety is off for the function scope
|
||||
const ssp_buf_size = owner_mod.stack_protector;
|
||||
if (ssp_buf_size != 0) {
|
||||
@ -2982,12 +3001,6 @@ pub const Object = struct {
|
||||
try attributes.addFnAttr(.minsize, &o.builder);
|
||||
try attributes.addFnAttr(.optsize, &o.builder);
|
||||
}
|
||||
if (owner_mod.sanitize_thread) {
|
||||
try attributes.addFnAttr(.sanitize_thread, &o.builder);
|
||||
}
|
||||
if (owner_mod.fuzz) {
|
||||
try attributes.addFnAttr(.optforfuzzing, &o.builder);
|
||||
}
|
||||
const target = owner_mod.resolved_target.result;
|
||||
if (target.cpu.model.llvm_name) |s| {
|
||||
try attributes.addFnAttr(.{ .string = .{
|
||||
|
||||
@ -524,6 +524,7 @@ const Writer = struct {
|
||||
.frame,
|
||||
.frame_address,
|
||||
.breakpoint,
|
||||
.disable_instrumentation,
|
||||
.c_va_start,
|
||||
.in_comptime,
|
||||
.value_placeholder,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user