authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-10-08 04:12:52+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-10-08 04:12:52+02:00
log41f8858304bb58b9f5c0a444d9705aed20aa66ed
tree9382e594bae922e9accd28ae9e606ae1e85ca620
parent54a25d82566393adad3befbe80a5113cb1f980c9
parent399eaa3d410da35de6f5d1869932a7c0e8ca46b2

Merge pull request 'compiler: lift some PIC restrictions and change the default' (#36532) from alexrp/zig:pic-stuff into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36532

4 files changed, 21 insertions(+), 18 deletions(-)

src/Module.zig+8-6
...@@ -174,7 +174,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {...@@ -174,7 +174,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {
174 };174 };
175175
176 const pic = b: {176 const pic = b: {
177 if (target_util.requiresPic(target, options.global.link_libc)) {177 if (target_util.requiresPic(target)) {
178 if (options.inherited.pic == false)178 if (options.inherited.pic == false)
179 return error.TargetRequiresPic;179 return error.TargetRequiresPic;
180 break :b true;180 break :b true;
...@@ -184,7 +184,10 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {...@@ -184,7 +184,10 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {
184 return error.PieRequiresPic;184 return error.PieRequiresPic;
185 break :b true;185 break :b true;
186 }186 }
187 if (options.global.link_mode == .dynamic and target_util.requiresPicForDynamicLink(target)) {187 if (options.global.output_mode == .Lib and
188 options.global.link_mode == .dynamic and
189 target_util.requiresPicForDynamicLink(target))
190 {
188 if (options.inherited.pic == false)191 if (options.inherited.pic == false)
189 return error.DynamicLinkingRequiresPic;192 return error.DynamicLinkingRequiresPic;
190 break :b true;193 break :b true;
...@@ -192,10 +195,9 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {...@@ -192,10 +195,9 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {
192 if (options.inherited.pic) |x| break :b x;195 if (options.inherited.pic) |x| break :b x;
193 if (options.parent) |p| break :b p.pic;196 if (options.parent) |p| break :b p.pic;
194197
195 // Default to PIC on targets where we default to producing PIEs to make198 // Default to PIC for objects and static libraries to make the common
196 // the common case of linking objects and static libraries into an199 // cases of linking those into a PIE or a shared library just work.
197 // executable work out of the box.200 break :b options.global.output_mode != .Exe;
198 break :b target_util.defaultPie(target);
199 };201 };
200202
201 const red_zone = b: {203 const red_zone = b: {
src/libs/glibc.zig+6-2
...@@ -243,7 +243,9 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -243,7 +243,9 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
243 };243 };
244 var files = [_]Compilation.CSourceFile{ start_o, abi_note_o, init_o };244 var files = [_]Compilation.CSourceFile{ start_o, abi_note_o, init_o };
245 const basename = if (comp.config.output_mode == .Exe and !comp.config.pie) "crt1" else "Scrt1";245 const basename = if (comp.config.output_mode == .Exe and !comp.config.pie) "crt1" else "Scrt1";
246 return comp.build_crt_file(basename, .Obj, .@"glibc Scrt1.o", prog_node, &files, .{});246 return comp.build_crt_file(basename, .Obj, .@"glibc Scrt1.o", prog_node, &files, .{
247 .pic = true,
248 });
247 },249 },
248 .libc_nonshared_a => {250 .libc_nonshared_a => {
249 const s = path.sep_str;251 const s = path.sep_str;
...@@ -356,7 +358,9 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -356,7 +358,9 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
356 files_index += 1;358 files_index += 1;
357 }359 }
358 const files = files_buf[0..files_index];360 const files = files_buf[0..files_index];
359 return comp.build_crt_file("c_nonshared", .Lib, .@"glibc libc_nonshared.a", prog_node, files, .{});361 return comp.build_crt_file("c_nonshared", .Lib, .@"glibc libc_nonshared.a", prog_node, files, .{
362 .pic = true,
363 });
360 },364 },
361 }365 }
362}366}
src/link/Elf2.zig+5-6
...@@ -9070,11 +9070,10 @@ fn addRelocAssumeCapacity(...@@ -9070,11 +9070,10 @@ fn addRelocAssumeCapacity(
9070 .PLT32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.pltabs, .{ .dest = .@"32", .cast = .unsigned, .shift = .@"0" })),9070 .PLT32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.pltabs, .{ .dest = .@"32", .cast = .unsigned, .shift = .@"0" })),
9071 .PLT64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.pltabs, .{ .dest = .@"64", .cast = .unsigned, .shift = .@"0" })),9071 .PLT64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.pltabs, .{ .dest = .@"64", .cast = .unsigned, .shift = .@"0" })),
90729072
9073 .WDISP30 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.rel, .{ .dest = .@"32[29:0]", .cast = .signed, .shift = .@"2_exact" })),9073 .WDISP30, .WPLT30 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.pltrel, .{ .dest = .@"32[29:0]", .cast = .signed, .shift = .@"2_exact" })),
9074 .WPLT30 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.pltrel, .{ .dest = .@"32[29:0]", .cast = .signed, .shift = .@"2_exact" })),9074 .PC22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.rel, .{ .dest = .@"32[21:0]", .cast = .unsigned, .shift = .@"10" })),
9075 .PC22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.rel, .{ .dest = .@"32[21:0]", .cast = .unsigned, .shift = .@"10" })),9075 .H44 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.abs, .{ .dest = .@"32[21:0]", .cast = .unsigned, .shift = .@"22" })),
9076 .H44 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.abs, .{ .dest = .@"32[21:0]", .cast = .unsigned, .shift = .@"22" })),9076 .M44 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.abs, .{ .dest = .@"32[9:0]", .cast = .trunc, .shift = .@"12" })),
9077 .M44 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.abs, .{ .dest = .@"32[9:0]", .cast = .trunc, .shift = .@"12" })),
90789077
9079 .TLS_LDO_HIX22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.dtpoff, .{ .dest = .@"32[21:0]", .cast = .trunc, .shift = .@"10" })),9078 .TLS_LDO_HIX22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.dtpoff, .{ .dest = .@"32[21:0]", .cast = .trunc, .shift = .@"10" })),
9080 .TLS_LE_HIX22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .special(.sparc_le_hix22)),9079 .TLS_LE_HIX22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .special(.sparc_le_hix22)),
...@@ -11944,7 +11943,7 @@ fn ensurePltEntry(elf: *Elf, gsi: Symbol.Global.Index) Error!bool {...@@ -11944,7 +11943,7 @@ fn ensurePltEntry(elf: *Elf, gsi: Symbol.Global.Index) Error!bool {
11944 // sethi (. - .plt[0]), %g111943 // sethi (. - .plt[0]), %g1
11945 .{ .imm22 = .{ .imm = @truncate(got_plt_offset), .op = 0b0000001100 } },11944 .{ .imm22 = .{ .imm = @truncate(got_plt_offset), .op = 0b0000001100 } },
11946 // ba,a %xcc, .plt[1]11945 // ba,a %xcc, .plt[1]
11947 .{ .disp19 = .{ .disp = @truncate((got_plt_offset + 4 - 32) >> 2), .op = 0b0011000001101 } },11946 .{ .disp19 = .{ .disp = @truncate((32 -% (got_plt_offset + 4)) >> 2), .op = 0b0011000001101 } },
11948 // nop11947 // nop
11949 .{ .raw = 0x0100_0000 },11948 .{ .raw = 0x0100_0000 },
11950 // nop11949 // nop
src/target.zig+2-4
...@@ -72,10 +72,8 @@ pub fn requiresPie(target: *const std.Target, link_mode: std.lang.LinkMode) bool...@@ -72,10 +72,8 @@ pub fn requiresPie(target: *const std.Target, link_mode: std.lang.LinkMode) bool
72}72}
7373
74/// This function returns whether non-pic code is completely invalid on the given target.74/// This function returns whether non-pic code is completely invalid on the given target.
75pub fn requiresPic(target: *const std.Target, linking_libc: bool) bool {75pub fn requiresPic(target: *const std.Target) bool {
76 return ((target.os.tag == .windows or target.os.tag == .uefi) and (target.cpu.arch == .aarch64 or target.cpu.arch == .x86_64)) or76 return (target.os.tag == .windows or target.os.tag == .uefi) and (target.cpu.arch == .aarch64 or target.cpu.arch == .x86_64);
77 target.requiresLibC() or
78 (linking_libc and target.isGnuLibC());
79}77}
8078
81pub fn requiresPicForDynamicLink(target: *const std.Target) bool {79pub fn requiresPicForDynamicLink(target: *const std.Target) bool {