Skip to content

Commit 7526b25

Browse files
committed
move libssp into libcompiler_rt
closes #7265
1 parent a54892f commit 7526b25

File tree

6 files changed

+60
-148
lines changed

6 files changed

+60
-148
lines changed

lib/compiler_rt.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,5 +233,6 @@ comptime {
233233
_ = @import("compiler_rt/memmove.zig");
234234
_ = @import("compiler_rt/memcmp.zig");
235235
_ = @import("compiler_rt/bcmp.zig");
236+
_ = @import("compiler_rt/ssp.zig");
236237
}
237238
}

lib/ssp.zig renamed to lib/compiler_rt/ssp.zig

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,43 +13,44 @@
1313
//! - __vsprintf_chk
1414

1515
const std = @import("std");
16+
const common = @import("./common.zig");
17+
const builtin = @import("builtin");
1618

1719
extern fn strncpy(dest: [*:0]u8, src: [*:0]const u8, n: usize) callconv(.C) [*:0]u8;
1820
extern fn memset(dest: ?[*]u8, c: u8, n: usize) callconv(.C) ?[*]u8;
1921
extern fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize) callconv(.C) ?[*]u8;
2022
extern fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) callconv(.C) ?[*]u8;
2123

22-
// Avoid dragging in the runtime safety mechanisms into this .o file.
23-
pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
24-
_ = msg;
25-
_ = error_return_trace;
26-
@setCold(true);
27-
std.os.abort();
24+
comptime {
25+
@export(__stack_chk_fail, .{ .name = "__stack_chk_fail", .linkage = common.linkage, .visibility = common.visibility });
26+
@export(__chk_fail, .{ .name = "__chk_fail", .linkage = common.linkage, .visibility = common.visibility });
27+
@export(__stack_chk_guard, .{ .name = "__stack_chk_guard", .linkage = common.linkage, .visibility = common.visibility });
28+
@export(__strcpy_chk, .{ .name = "__strcpy_chk", .linkage = common.linkage, .visibility = common.visibility });
29+
@export(__strncpy_chk, .{ .name = "__strncpy_chk", .linkage = common.linkage, .visibility = common.visibility });
30+
@export(__strcat_chk, .{ .name = "__strcat_chk", .linkage = common.linkage, .visibility = common.visibility });
31+
@export(__strncat_chk, .{ .name = "__strncat_chk", .linkage = common.linkage, .visibility = common.visibility });
32+
@export(__memcpy_chk, .{ .name = "__memcpy_chk", .linkage = common.linkage, .visibility = common.visibility });
33+
@export(__memmove_chk, .{ .name = "__memmove_chk", .linkage = common.linkage, .visibility = common.visibility });
34+
@export(__memset_chk, .{ .name = "__memset_chk", .linkage = common.linkage, .visibility = common.visibility });
2835
}
2936

30-
export fn __stack_chk_fail() callconv(.C) noreturn {
37+
fn __stack_chk_fail() callconv(.C) noreturn {
3138
@panic("stack smashing detected");
3239
}
3340

34-
export fn __chk_fail() callconv(.C) noreturn {
41+
fn __chk_fail() callconv(.C) noreturn {
3542
@panic("buffer overflow detected");
3643
}
3744

38-
// Emitted when targeting some architectures (eg. x86)
39-
// XXX: This symbol should be hidden
40-
export fn __stack_chk_fail_local() callconv(.C) noreturn {
41-
__stack_chk_fail();
42-
}
43-
44-
// XXX: Initialize the canary with random data
45-
export var __stack_chk_guard: usize = blk: {
45+
// TODO: Initialize the canary with random data
46+
var __stack_chk_guard: usize = blk: {
4647
var buf = [1]u8{0} ** @sizeOf(usize);
4748
buf[@sizeOf(usize) - 1] = 255;
4849
buf[@sizeOf(usize) - 2] = '\n';
4950
break :blk @as(usize, @bitCast(buf));
5051
};
5152

52-
export fn __strcpy_chk(dest: [*:0]u8, src: [*:0]const u8, dest_n: usize) callconv(.C) [*:0]u8 {
53+
fn __strcpy_chk(dest: [*:0]u8, src: [*:0]const u8, dest_n: usize) callconv(.C) [*:0]u8 {
5354
@setRuntimeSafety(false);
5455

5556
var i: usize = 0;
@@ -64,12 +65,12 @@ export fn __strcpy_chk(dest: [*:0]u8, src: [*:0]const u8, dest_n: usize) callcon
6465
return dest;
6566
}
6667

67-
export fn __strncpy_chk(dest: [*:0]u8, src: [*:0]const u8, n: usize, dest_n: usize) callconv(.C) [*:0]u8 {
68+
fn __strncpy_chk(dest: [*:0]u8, src: [*:0]const u8, n: usize, dest_n: usize) callconv(.C) [*:0]u8 {
6869
if (dest_n < n) __chk_fail();
6970
return strncpy(dest, src, n);
7071
}
7172

72-
export fn __strcat_chk(dest: [*:0]u8, src: [*:0]const u8, dest_n: usize) callconv(.C) [*:0]u8 {
73+
fn __strcat_chk(dest: [*:0]u8, src: [*:0]const u8, dest_n: usize) callconv(.C) [*:0]u8 {
7374
@setRuntimeSafety(false);
7475

7576
var avail = dest_n;
@@ -94,7 +95,7 @@ export fn __strcat_chk(dest: [*:0]u8, src: [*:0]const u8, dest_n: usize) callcon
9495
return dest;
9596
}
9697

97-
export fn __strncat_chk(dest: [*:0]u8, src: [*:0]const u8, n: usize, dest_n: usize) callconv(.C) [*:0]u8 {
98+
fn __strncat_chk(dest: [*:0]u8, src: [*:0]const u8, n: usize, dest_n: usize) callconv(.C) [*:0]u8 {
9899
@setRuntimeSafety(false);
99100

100101
var avail = dest_n;
@@ -119,17 +120,17 @@ export fn __strncat_chk(dest: [*:0]u8, src: [*:0]const u8, n: usize, dest_n: usi
119120
return dest;
120121
}
121122

122-
export fn __memcpy_chk(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize, dest_n: usize) callconv(.C) ?[*]u8 {
123+
fn __memcpy_chk(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize, dest_n: usize) callconv(.C) ?[*]u8 {
123124
if (dest_n < n) __chk_fail();
124125
return memcpy(dest, src, n);
125126
}
126127

127-
export fn __memmove_chk(dest: ?[*]u8, src: ?[*]const u8, n: usize, dest_n: usize) callconv(.C) ?[*]u8 {
128+
fn __memmove_chk(dest: ?[*]u8, src: ?[*]const u8, n: usize, dest_n: usize) callconv(.C) ?[*]u8 {
128129
if (dest_n < n) __chk_fail();
129130
return memmove(dest, src, n);
130131
}
131132

132-
export fn __memset_chk(dest: ?[*]u8, c: u8, n: usize, dest_n: usize) callconv(.C) ?[*]u8 {
133+
fn __memset_chk(dest: ?[*]u8, c: u8, n: usize, dest_n: usize) callconv(.C) ?[*]u8 {
133134
if (dest_n < n) __chk_fail();
134135
return memset(dest, c, n);
135136
}

src/Compilation.zig

Lines changed: 22 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,6 @@ libunwind_static_lib: ?CRTFile = null,
152152
/// Populated when we build the TSAN static library. A Job to build this is placed in the queue
153153
/// and resolved before calling linker.flush().
154154
tsan_static_lib: ?CRTFile = null,
155-
/// Populated when we build the libssp static library. A Job to build this is placed in the queue
156-
/// and resolved before calling linker.flush().
157-
libssp_static_lib: ?CRTFile = null,
158155
/// Populated when we build the libc static library. A Job to build this is placed in the queue
159156
/// and resolved before calling linker.flush().
160157
libc_static_lib: ?CRTFile = null,
@@ -286,7 +283,6 @@ const Job = union(enum) {
286283
libcxx: void,
287284
libcxxabi: void,
288285
libtsan: void,
289-
libssp: void,
290286
/// needed when not linking libc and using LLVM for code generation because it generates
291287
/// calls to, for example, memcpy and memset.
292288
zig_libc: void,
@@ -412,7 +408,6 @@ pub const MiscTask = enum {
412408
libtsan,
413409
wasi_libc_crt_file,
414410
compiler_rt,
415-
libssp,
416411
zig_libc,
417412
analyze_mod,
418413

@@ -1082,10 +1077,14 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
10821077
if (stack_check and !target_util.supportsStackProbing(options.target))
10831078
return error.StackCheckUnsupportedByTarget;
10841079

1085-
const capable_of_building_ssp = canBuildLibSsp(options.target, use_llvm);
1086-
1087-
const stack_protector: u32 = options.want_stack_protector orelse b: {
1088-
if (!target_util.supportsStackProtector(options.target)) break :b @as(u32, 0);
1080+
const stack_protector: u32 = sp: {
1081+
const zig_backend = zigBackend(options.target, use_llvm);
1082+
if (!target_util.supportsStackProtector(options.target, zig_backend)) {
1083+
if (options.want_stack_protector) |x| {
1084+
if (x > 0) return error.StackProtectorUnsupportedByTarget;
1085+
}
1086+
break :sp 0;
1087+
}
10891088

10901089
// This logic is checking for linking libc because otherwise our start code
10911090
// which is trying to set up TLS (i.e. the fs/gs registers) but the stack
@@ -1094,19 +1093,17 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
10941093
// as being exempt from stack protection checks, we could change this logic
10951094
// to supporting stack protection even when not linking libc.
10961095
// TODO file issue about this
1097-
if (!link_libc) break :b 0;
1098-
if (!capable_of_building_ssp) break :b 0;
1099-
if (is_safe_mode) break :b default_stack_protector_buffer_size;
1100-
break :b 0;
1096+
if (!link_libc) {
1097+
if (options.want_stack_protector) |x| {
1098+
if (x > 0) return error.StackProtectorUnavailableWithoutLibC;
1099+
}
1100+
break :sp 0;
1101+
}
1102+
1103+
if (options.want_stack_protector) |x| break :sp x;
1104+
if (is_safe_mode) break :sp default_stack_protector_buffer_size;
1105+
break :sp 0;
11011106
};
1102-
if (stack_protector != 0) {
1103-
if (!target_util.supportsStackProtector(options.target))
1104-
return error.StackProtectorUnsupportedByTarget;
1105-
if (!capable_of_building_ssp)
1106-
return error.StackProtectorUnsupportedByBackend;
1107-
if (!link_libc)
1108-
return error.StackProtectorUnavailableWithoutLibC;
1109-
}
11101107

11111108
const include_compiler_rt = options.want_compiler_rt orelse
11121109
(!options.skip_linker_dependencies and is_exe_or_dyn_lib);
@@ -1924,24 +1921,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
19241921
comp.job_queued_compiler_rt_obj = true;
19251922
}
19261923
}
1927-
if (needsCSymbols(
1928-
options.skip_linker_dependencies,
1929-
options.output_mode,
1930-
options.link_mode,
1931-
options.target,
1932-
comp.bin_file.options.use_llvm,
1933-
)) {
1934-
// Related: https://github.com/ziglang/zig/issues/7265.
1935-
if (comp.bin_file.options.stack_protector != 0 and
1936-
(!comp.bin_file.options.link_libc or
1937-
!target_util.libcProvidesStackProtector(target)))
1938-
{
1939-
try comp.work_queue.writeItem(.{ .libssp = {} });
1940-
}
19411924

1942-
if (!comp.bin_file.options.link_libc and capable_of_building_zig_libc) {
1943-
try comp.work_queue.writeItem(.{ .zig_libc = {} });
1944-
}
1925+
if (!comp.bin_file.options.skip_linker_dependencies and is_exe_or_dyn_lib and
1926+
!comp.bin_file.options.link_libc and capable_of_building_zig_libc)
1927+
{
1928+
try comp.work_queue.writeItem(.{ .zig_libc = {} });
19451929
}
19461930
}
19471931

@@ -1987,9 +1971,6 @@ pub fn destroy(self: *Compilation) void {
19871971
if (self.compiler_rt_obj) |*crt_file| {
19881972
crt_file.deinit(gpa);
19891973
}
1990-
if (self.libssp_static_lib) |*crt_file| {
1991-
crt_file.deinit(gpa);
1992-
}
19931974
if (self.libc_static_lib) |*crt_file| {
19941975
crt_file.deinit(gpa);
19951976
}
@@ -3768,26 +3749,6 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
37683749
);
37693750
};
37703751
},
3771-
.libssp => {
3772-
const named_frame = tracy.namedFrame("libssp");
3773-
defer named_frame.end();
3774-
3775-
comp.buildOutputFromZig(
3776-
"ssp.zig",
3777-
.Lib,
3778-
&comp.libssp_static_lib,
3779-
.libssp,
3780-
prog_node,
3781-
) catch |err| switch (err) {
3782-
error.OutOfMemory => return error.OutOfMemory,
3783-
error.SubCompilationFailed => return, // error reported already
3784-
else => comp.lockAndSetMiscFailure(
3785-
.libssp,
3786-
"unable to build libssp: {s}",
3787-
.{@errorName(err)},
3788-
),
3789-
};
3790-
},
37913752
.zig_libc => {
37923753
const named_frame = tracy.namedFrame("zig_libc");
37933754
defer named_frame.end();
@@ -6271,21 +6232,6 @@ fn canBuildLibCompilerRt(target: std.Target, use_llvm: bool) bool {
62716232
};
62726233
}
62736234

6274-
fn canBuildLibSsp(target: std.Target, use_llvm: bool) bool {
6275-
switch (target.os.tag) {
6276-
.plan9 => return false,
6277-
else => {},
6278-
}
6279-
switch (target.cpu.arch) {
6280-
.spirv32, .spirv64 => return false,
6281-
else => {},
6282-
}
6283-
return switch (zigBackend(target, use_llvm)) {
6284-
.stage2_llvm => true,
6285-
else => build_options.have_llvm,
6286-
};
6287-
}
6288-
62896235
/// Not to be confused with canBuildLibC, which builds musl, glibc, and similar.
62906236
/// This one builds lib/c.zig.
62916237
fn canBuildZigLibC(target: std.Target, use_llvm: bool) bool {
@@ -6325,29 +6271,6 @@ fn zigBackend(target: std.Target, use_llvm: bool) std.builtin.CompilerBackend {
63256271
};
63266272
}
63276273

6328-
fn needsCSymbols(
6329-
skip_linker_dependencies: bool,
6330-
output_mode: std.builtin.OutputMode,
6331-
link_mode: ?std.builtin.LinkMode,
6332-
target: std.Target,
6333-
use_llvm: bool,
6334-
) bool {
6335-
if (skip_linker_dependencies)
6336-
return false;
6337-
6338-
switch (output_mode) {
6339-
.Obj => return false,
6340-
.Lib => if (link_mode != .Dynamic) return false,
6341-
.Exe => {},
6342-
}
6343-
6344-
// LLVM might generate calls to libc symbols.
6345-
if (zigBackend(target, use_llvm) == .stage2_llvm)
6346-
return true;
6347-
6348-
return false;
6349-
}
6350-
63516274
pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Allocator.Error![:0]u8 {
63526275
const tracy_trace = trace(@src());
63536276
defer tracy_trace.end();

src/link/Coff/lld.zig

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -483,12 +483,6 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
483483
try argv.append(lib.full_object_path);
484484
}
485485
}
486-
// MinGW doesn't provide libssp symbols
487-
if (target.abi.isGnu()) {
488-
if (comp.libssp_static_lib) |lib| {
489-
try argv.append(lib.full_object_path);
490-
}
491-
}
492486
// MSVC compiler_rt is missing some stuff, so we build it unconditionally but
493487
// and rely on weak linkage to allow MSVC compiler_rt functions to override ours.
494488
if (comp.compiler_rt_obj) |obj| try argv.append(obj.full_object_path);

src/link/Elf.zig

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,12 +1134,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
11341134
}
11351135
}
11361136

1137-
// stack-protector.
1138-
// Related: https://github.com/ziglang/zig/issues/7265
1139-
if (comp.libssp_static_lib) |ssp| {
1140-
try argv.append(ssp.full_object_path);
1141-
}
1142-
11431137
// Shared libraries.
11441138
// Worst-case, we need an --as-needed argument for every lib, as well
11451139
// as one before and one after.
@@ -1277,12 +1271,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
12771271
}
12781272
}
12791273

1280-
// stack-protector.
1281-
// Related: https://github.com/ziglang/zig/issues/7265
1282-
if (comp.libssp_static_lib) |ssp| {
1283-
try positionals.append(.{ .path = ssp.full_object_path });
1284-
}
1285-
12861274
for (positionals.items) |obj| {
12871275
var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined };
12881276
self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err|
@@ -2623,12 +2611,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
26232611
}
26242612
}
26252613

2626-
// stack-protector.
2627-
// Related: https://github.com/ziglang/zig/issues/7265
2628-
if (comp.libssp_static_lib) |ssp| {
2629-
try argv.append(ssp.full_object_path);
2630-
}
2631-
26322614
// Shared libraries.
26332615
if (is_exe_or_dyn_lib) {
26342616
const system_libs = self.base.options.system_libs.keys();

src/target.zig

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,19 @@ pub fn supportsStackProbing(target: std.Target) bool {
328328
(target.cpu.arch == .x86 or target.cpu.arch == .x86_64);
329329
}
330330

331-
pub fn supportsStackProtector(target: std.Target) bool {
332-
return !target.isSpirV();
331+
pub fn supportsStackProtector(target: std.Target, backend: std.builtin.CompilerBackend) bool {
332+
switch (target.os.tag) {
333+
.plan9 => return false,
334+
else => {},
335+
}
336+
switch (target.cpu.arch) {
337+
.spirv32, .spirv64 => return false,
338+
else => {},
339+
}
340+
return switch (backend) {
341+
.stage2_llvm => true,
342+
else => false,
343+
};
333344
}
334345

335346
pub fn libcProvidesStackProtector(target: std.Target) bool {

0 commit comments

Comments
 (0)