authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-12-13 03:09:24+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-12-13 03:09:24+01:00
log130f7c2ed8e3358e24bb2fc7cca57f7a6f1f85c3
treeebb88312b13fb8b1e67b852bcb0e42903ad11193
parentd48611ba67c7871cb348f28a01b89d8771170dd8
parentc666ebb1f8aac440a4d0d554e9f8aa836bf58060
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #22035 from alexrp/unwind-fixes

Better unwind table support + unwind protection in `_start()` and `clone()`

45 files changed, 361 insertions(+), 138 deletions(-)

lib/libc/musl/src/thread/aarch64/clone.s+2-1
...@@ -24,7 +24,8 @@ __clone:...@@ -24,7 +24,8 @@ __clone:
24 // parent24 // parent
25 ret25 ret
26 // child26 // child
271: ldp x1,x0,[sp],#16271: mov fp, 0
28 ldp x1,x0,[sp],#16
28 blr x129 blr x1
29 mov x8,#93 // SYS_exit30 mov x8,#93 // SYS_exit
30 svc #031 svc #0
lib/libc/musl/src/thread/arm/clone.s+2-1
...@@ -19,7 +19,8 @@ __clone:...@@ -19,7 +19,8 @@ __clone:
19 ldmfd sp!,{r4,r5,r6,r7}19 ldmfd sp!,{r4,r5,r6,r7}
20 bx lr20 bx lr
2121
221: mov r0,r6221: mov fp,#0
23 mov r0,r6
23 bl 3f24 bl 3f
242: mov r7,#1252: mov r7,#1
25 svc 026 svc 0
lib/libc/musl/src/thread/i386/clone.s+8-9
...@@ -30,9 +30,15 @@ __clone:...@@ -30,9 +30,15 @@ __clone:
30 mov 8(%ebp),%ebp30 mov 8(%ebp),%ebp
31 int $12831 int $128
32 test %eax,%eax32 test %eax,%eax
33 jnz 1f33 jz 1f
34 add $16,%esp
35 pop %edi
36 pop %esi
37 pop %ebx
38 pop %ebp
39 ret
3440
35 mov %ebp,%eax411: mov %ebp,%eax
36 xor %ebp,%ebp42 xor %ebp,%ebp
37 call *%eax43 call *%eax
38 mov %eax,%ebx44 mov %eax,%ebx
...@@ -40,10 +46,3 @@ __clone:...@@ -40,10 +46,3 @@ __clone:
40 inc %eax46 inc %eax
41 int $12847 int $128
42 hlt48 hlt
43
441: add $16,%esp
45 pop %edi
46 pop %esi
47 pop %ebx
48 pop %ebp
49 ret
lib/libc/musl/src/thread/loongarch64/clone.s+1
...@@ -22,6 +22,7 @@ __clone:...@@ -22,6 +22,7 @@ __clone:
22 beqz $a0, 1f # whether child process22 beqz $a0, 1f # whether child process
23 jirl $zero, $ra, 0 # parent process return23 jirl $zero, $ra, 0 # parent process return
241:241:
25 move $fp, $zero
25 ld.d $t8, $sp, 0 # function pointer26 ld.d $t8, $sp, 0 # function pointer
26 ld.d $a0, $sp, 8 # argument pointer27 ld.d $a0, $sp, 8 # argument pointer
27 jirl $ra, $t8, 0 # call the user's function28 jirl $ra, $t8, 0 # call the user's function
lib/libc/musl/src/thread/m68k/clone.s+2-1
...@@ -18,7 +18,8 @@ __clone:...@@ -18,7 +18,8 @@ __clone:
18 beq 1f18 beq 1f
19 movem.l (%sp)+,%d2-%d519 movem.l (%sp)+,%d2-%d5
20 rts20 rts
211: move.l %a1,-(%sp)211: suba.l %%fp,%%fp
22 move.l %a1,-(%sp)
22 jsr (%a0)23 jsr (%a0)
23 move.l #1,%d024 move.l #1,%d0
24 trap #025 trap #0
lib/libc/musl/src/thread/microblaze/clone.s+2-1
...@@ -22,7 +22,8 @@ __clone:...@@ -22,7 +22,8 @@ __clone:
22 rtsd r15, 822 rtsd r15, 8
23 nop23 nop
2424
251: lwi r3, r1, 0251: add r19, r0, r0
26 lwi r3, r1, 0
26 lwi r5, r1, 427 lwi r5, r1, 4
27 brald r15, r328 brald r15, r3
28 nop29 nop
lib/libc/musl/src/thread/mips/clone.s+2-1
...@@ -27,7 +27,8 @@ __clone:...@@ -27,7 +27,8 @@ __clone:
27 addu $sp, $sp, 1627 addu $sp, $sp, 16
28 jr $ra28 jr $ra
29 nop29 nop
301: lw $25, 0($sp)301: move $fp, $0
31 lw $25, 0($sp)
31 lw $4, 4($sp)32 lw $4, 4($sp)
32 jalr $2533 jalr $25
33 nop34 nop
lib/libc/musl/src/thread/mips64/clone.s+2-1
...@@ -25,7 +25,8 @@ __clone:...@@ -25,7 +25,8 @@ __clone:
25 nop25 nop
26 jr $ra26 jr $ra
27 nop27 nop
281: ld $25, 0($sp) # function pointer281: move $fp, $0
29 ld $25, 0($sp) # function pointer
29 ld $4, 8($sp) # argument pointer30 ld $4, 8($sp) # argument pointer
30 jalr $25 # call the user's function31 jalr $25 # call the user's function
31 nop32 nop
lib/libc/musl/src/thread/mipsn32/clone.s+2-1
...@@ -25,7 +25,8 @@ __clone:...@@ -25,7 +25,8 @@ __clone:
25 nop25 nop
26 jr $ra26 jr $ra
27 nop27 nop
281: lw $25, 0($sp) # function pointer281: move $fp, $0
29 lw $25, 0($sp) # function pointer
29 lw $4, 4($sp) # argument pointer30 lw $4, 4($sp) # argument pointer
30 jalr $25 # call the user's function31 jalr $25 # call the user's function
31 nop32 nop
lib/libc/musl/src/thread/or1k/clone.s+2-1
...@@ -23,7 +23,8 @@ __clone:...@@ -23,7 +23,8 @@ __clone:
23 l.jr r923 l.jr r9
24 l.nop24 l.nop
2525
261: l.lwz r11, 0(r1)261: l.ori r2, r0, 0
27 l.lwz r11, 0(r1)
27 l.jalr r1128 l.jalr r11
28 l.lwz r3, 4(r1)29 l.lwz r3, 4(r1)
2930
lib/libc/musl/src/thread/powerpc/clone.s+9-12
...@@ -48,9 +48,16 @@ neg 3, 3 #negate the result (errno)...@@ -48,9 +48,16 @@ neg 3, 3 #negate the result (errno)
48# compare sc result with 048# compare sc result with 0
49cmpwi cr7, 3, 049cmpwi cr7, 3, 0
5050
51# if not 0, jump to end51# if not 0, restore stack and return
52bne cr7, 2f52beq cr7, 2f
5353
54lwz 30, 0(1)
55lwz 31, 4(1)
56addi 1, 1, 16
57
58blr
59
602:
54#else: we're the child61#else: we're the child
55#call funcptr: move arg (d) into r362#call funcptr: move arg (d) into r3
56mr 3, 3163mr 3, 31
...@@ -61,13 +68,3 @@ bctrl...@@ -61,13 +68,3 @@ bctrl
61# mov SYS_exit into r0 (the exit param is already in r3)68# mov SYS_exit into r0 (the exit param is already in r3)
62li 0, 169li 0, 1
63sc70sc
64
652:
66
67# restore stack
68lwz 30, 0(1)
69lwz 31, 4(1)
70addi 1, 1, 16
71
72blr
73
lib/libc/musl/src/thread/x32/clone.s+3-3
...@@ -15,12 +15,12 @@ __clone:...@@ -15,12 +15,12 @@ __clone:
15 mov %rcx,(%rsi)15 mov %rcx,(%rsi)
16 syscall16 syscall
17 test %eax,%eax17 test %eax,%eax
18 jnz 1f18 jz 1f
19 xor %ebp,%ebp19 ret
201: xor %ebp,%ebp
20 pop %rdi21 pop %rdi
21 call *%r922 call *%r9
22 mov %eax,%edi23 mov %eax,%edi
23 movl $0x4000003c,%eax /* SYS_exit */24 movl $0x4000003c,%eax /* SYS_exit */
24 syscall25 syscall
25 hlt26 hlt
261: ret
lib/libc/musl/src/thread/x86_64/clone.s+3-3
...@@ -16,8 +16,9 @@ __clone:...@@ -16,8 +16,9 @@ __clone:
16 mov %rcx,(%rsi)16 mov %rcx,(%rsi)
17 syscall17 syscall
18 test %eax,%eax18 test %eax,%eax
19 jnz 1f19 jz 1f
20 xor %ebp,%ebp20 ret
211: xor %ebp,%ebp
21 pop %rdi22 pop %rdi
22 call *%r923 call *%r9
23 mov %eax,%edi24 mov %eax,%edi
...@@ -25,4 +26,3 @@ __clone:...@@ -25,4 +26,3 @@ __clone:
25 mov $60,%al26 mov $60,%al
26 syscall27 syscall
27 hlt28 hlt
281: ret
lib/std/Build.zig+5-5
...@@ -706,7 +706,7 @@ pub const ExecutableOptions = struct {...@@ -706,7 +706,7 @@ pub const ExecutableOptions = struct {
706 single_threaded: ?bool = null,706 single_threaded: ?bool = null,
707 pic: ?bool = null,707 pic: ?bool = null,
708 strip: ?bool = null,708 strip: ?bool = null,
709 unwind_tables: ?bool = null,709 unwind_tables: ?std.builtin.UnwindTables = null,
710 omit_frame_pointer: ?bool = null,710 omit_frame_pointer: ?bool = null,
711 sanitize_thread: ?bool = null,711 sanitize_thread: ?bool = null,
712 error_tracing: ?bool = null,712 error_tracing: ?bool = null,
...@@ -762,7 +762,7 @@ pub const ObjectOptions = struct {...@@ -762,7 +762,7 @@ pub const ObjectOptions = struct {
762 single_threaded: ?bool = null,762 single_threaded: ?bool = null,
763 pic: ?bool = null,763 pic: ?bool = null,
764 strip: ?bool = null,764 strip: ?bool = null,
765 unwind_tables: ?bool = null,765 unwind_tables: ?std.builtin.UnwindTables = null,
766 omit_frame_pointer: ?bool = null,766 omit_frame_pointer: ?bool = null,
767 sanitize_thread: ?bool = null,767 sanitize_thread: ?bool = null,
768 error_tracing: ?bool = null,768 error_tracing: ?bool = null,
...@@ -810,7 +810,7 @@ pub const SharedLibraryOptions = struct {...@@ -810,7 +810,7 @@ pub const SharedLibraryOptions = struct {
810 single_threaded: ?bool = null,810 single_threaded: ?bool = null,
811 pic: ?bool = null,811 pic: ?bool = null,
812 strip: ?bool = null,812 strip: ?bool = null,
813 unwind_tables: ?bool = null,813 unwind_tables: ?std.builtin.UnwindTables = null,
814 omit_frame_pointer: ?bool = null,814 omit_frame_pointer: ?bool = null,
815 sanitize_thread: ?bool = null,815 sanitize_thread: ?bool = null,
816 error_tracing: ?bool = null,816 error_tracing: ?bool = null,
...@@ -867,7 +867,7 @@ pub const StaticLibraryOptions = struct {...@@ -867,7 +867,7 @@ pub const StaticLibraryOptions = struct {
867 single_threaded: ?bool = null,867 single_threaded: ?bool = null,
868 pic: ?bool = null,868 pic: ?bool = null,
869 strip: ?bool = null,869 strip: ?bool = null,
870 unwind_tables: ?bool = null,870 unwind_tables: ?std.builtin.UnwindTables = null,
871 omit_frame_pointer: ?bool = null,871 omit_frame_pointer: ?bool = null,
872 sanitize_thread: ?bool = null,872 sanitize_thread: ?bool = null,
873 error_tracing: ?bool = null,873 error_tracing: ?bool = null,
...@@ -919,7 +919,7 @@ pub const TestOptions = struct {...@@ -919,7 +919,7 @@ pub const TestOptions = struct {
919 single_threaded: ?bool = null,919 single_threaded: ?bool = null,
920 pic: ?bool = null,920 pic: ?bool = null,
921 strip: ?bool = null,921 strip: ?bool = null,
922 unwind_tables: ?bool = null,922 unwind_tables: ?std.builtin.UnwindTables = null,
923 omit_frame_pointer: ?bool = null,923 omit_frame_pointer: ?bool = null,
924 sanitize_thread: ?bool = null,924 sanitize_thread: ?bool = null,
925 error_tracing: ?bool = null,925 error_tracing: ?bool = null,
lib/std/Build/Module.zig+10-3
...@@ -22,7 +22,7 @@ frameworks: std.StringArrayHashMapUnmanaged(LinkFrameworkOptions),...@@ -22,7 +22,7 @@ frameworks: std.StringArrayHashMapUnmanaged(LinkFrameworkOptions),
22link_objects: std.ArrayListUnmanaged(LinkObject),22link_objects: std.ArrayListUnmanaged(LinkObject),
2323
24strip: ?bool,24strip: ?bool,
25unwind_tables: ?bool,25unwind_tables: ?std.builtin.UnwindTables,
26single_threaded: ?bool,26single_threaded: ?bool,
27stack_protector: ?bool,27stack_protector: ?bool,
28stack_check: ?bool,28stack_check: ?bool,
...@@ -218,7 +218,7 @@ pub const CreateOptions = struct {...@@ -218,7 +218,7 @@ pub const CreateOptions = struct {
218 link_libcpp: ?bool = null,218 link_libcpp: ?bool = null,
219 single_threaded: ?bool = null,219 single_threaded: ?bool = null,
220 strip: ?bool = null,220 strip: ?bool = null,
221 unwind_tables: ?bool = null,221 unwind_tables: ?std.builtin.UnwindTables = null,
222 dwarf_format: ?std.dwarf.Format = null,222 dwarf_format: ?std.dwarf.Format = null,
223 code_model: std.builtin.CodeModel = .default,223 code_model: std.builtin.CodeModel = .default,
224 stack_protector: ?bool = null,224 stack_protector: ?bool = null,
...@@ -675,7 +675,6 @@ pub fn appendZigProcessFlags(...@@ -675,7 +675,6 @@ pub fn appendZigProcessFlags(
675 const b = m.owner;675 const b = m.owner;
676676
677 try addFlag(zig_args, m.strip, "-fstrip", "-fno-strip");677 try addFlag(zig_args, m.strip, "-fstrip", "-fno-strip");
678 try addFlag(zig_args, m.unwind_tables, "-funwind-tables", "-fno-unwind-tables");
679 try addFlag(zig_args, m.single_threaded, "-fsingle-threaded", "-fno-single-threaded");678 try addFlag(zig_args, m.single_threaded, "-fsingle-threaded", "-fno-single-threaded");
680 try addFlag(zig_args, m.stack_check, "-fstack-check", "-fno-stack-check");679 try addFlag(zig_args, m.stack_check, "-fstack-check", "-fno-stack-check");
681 try addFlag(zig_args, m.stack_protector, "-fstack-protector", "-fno-stack-protector");680 try addFlag(zig_args, m.stack_protector, "-fstack-protector", "-fno-stack-protector");
...@@ -695,6 +694,14 @@ pub fn appendZigProcessFlags(...@@ -695,6 +694,14 @@ pub fn appendZigProcessFlags(
695 });694 });
696 }695 }
697696
697 if (m.unwind_tables) |unwind_tables| {
698 try zig_args.append(switch (unwind_tables) {
699 .none => "-fno-unwind-tables",
700 .sync => "-funwind-tables",
701 .@"async" => "-fasync-unwind-tables",
702 });
703 }
704
698 try zig_args.ensureUnusedCapacity(1);705 try zig_args.ensureUnusedCapacity(1);
699 if (m.optimize) |optimize| switch (optimize) {706 if (m.optimize) |optimize| switch (optimize) {
700 .Debug => zig_args.appendAssumeCapacity("-ODebug"),707 .Debug => zig_args.appendAssumeCapacity("-ODebug"),
lib/std/builtin.zig+8
...@@ -804,6 +804,14 @@ pub const LinkMode = enum {...@@ -804,6 +804,14 @@ pub const LinkMode = enum {
804 dynamic,804 dynamic,
805};805};
806806
807/// This data structure is used by the Zig language code generation and
808/// therefore must be kept in sync with the compiler implementation.
809pub const UnwindTables = enum {
810 none,
811 sync,
812 @"async",
813};
814
807/// This data structure is used by the Zig language code generation and815/// This data structure is used by the Zig language code generation and
808/// therefore must be kept in sync with the compiler implementation.816/// therefore must be kept in sync with the compiler implementation.
809pub const WasiExecModel = enum {817pub const WasiExecModel = enum {
lib/std/os/linux/aarch64.zig+6-1
...@@ -120,8 +120,13 @@ pub fn clone() callconv(.Naked) usize {...@@ -120,8 +120,13 @@ pub fn clone() callconv(.Naked) usize {
120 \\ cbz x0,1f120 \\ cbz x0,1f
121 \\ // parent121 \\ // parent
122 \\ ret122 \\ ret
123 \\
123 \\ // child124 \\ // child
124 \\1: ldp x1,x0,[sp],#16125 \\1: .cfi_undefined lr
126 \\ mov fp, 0
127 \\ mov lr, 0
128 \\
129 \\ ldp x1,x0,[sp],#16
125 \\ blr x1130 \\ blr x1
126 \\ mov x8,#93 // SYS_exit131 \\ mov x8,#93 // SYS_exit
127 \\ svc #0132 \\ svc #0
lib/std/os/linux/arm.zig+8-3
...@@ -120,11 +120,16 @@ pub fn clone() callconv(.Naked) usize {...@@ -120,11 +120,16 @@ pub fn clone() callconv(.Naked) usize {
120 \\ ldmfd sp!,{r4,r5,r6,r7}120 \\ ldmfd sp!,{r4,r5,r6,r7}
121 \\ bx lr121 \\ bx lr
122 \\122 \\
123 \\1: mov r0,r6123 \\ // https://github.com/llvm/llvm-project/issues/115891
124 \\1: mov r7, #0
125 \\ mov r11, #0
126 \\ mov lr, #0
127 \\
128 \\ mov r0,r6
124 \\ bl 3f129 \\ bl 3f
125 \\2: mov r7,#1 // SYS_exit130 \\ mov r7,#1 // SYS_exit
126 \\ svc 0131 \\ svc 0
127 \\ b 2b132 \\
128 \\3: bx r5133 \\3: bx r5
129 );134 );
130}135}
lib/std/os/linux/hexagon.zig+4
...@@ -118,6 +118,10 @@ pub fn clone() callconv(.Naked) usize {...@@ -118,6 +118,10 @@ pub fn clone() callconv(.Naked) usize {
118 \\ p0 = cmp.eq(r0, #0)118 \\ p0 = cmp.eq(r0, #0)
119 \\ if (!p0) dealloc_return119 \\ if (!p0) dealloc_return
120 \\120 \\
121 \\ .cfi_undefined r31
122 \\ r30 = #0
123 \\ r31 = #0
124 \\
121 \\ r0 = r10125 \\ r0 = r10
122 \\ callr r11126 \\ callr r11
123 \\127 \\
lib/std/os/linux/loongarch64.zig+4
...@@ -121,6 +121,10 @@ pub fn clone() callconv(.Naked) usize {...@@ -121,6 +121,10 @@ pub fn clone() callconv(.Naked) usize {
121 \\ beqz $a0, 1f # whether child process121 \\ beqz $a0, 1f # whether child process
122 \\ jirl $zero, $ra, 0 # parent process return122 \\ jirl $zero, $ra, 0 # parent process return
123 \\1:123 \\1:
124 \\ .cfi_undefined 1
125 \\ move $fp, $zero
126 \\ move $ra, $zero
127 \\
124 \\ ld.d $t8, $sp, 0 # function pointer128 \\ ld.d $t8, $sp, 0 # function pointer
125 \\ ld.d $a0, $sp, 8 # argument pointer129 \\ ld.d $a0, $sp, 8 # argument pointer
126 \\ jirl $ra, $t8, 0 # call the user's function130 \\ jirl $ra, $t8, 0 # call the user's function
lib/std/os/linux/mips.zig+4
...@@ -231,6 +231,10 @@ pub fn clone() callconv(.Naked) usize {...@@ -231,6 +231,10 @@ pub fn clone() callconv(.Naked) usize {
231 \\ jr $ra231 \\ jr $ra
232 \\ nop232 \\ nop
233 \\1:233 \\1:
234 \\ .cfi_undefined $ra
235 \\ move $fp, $zero
236 \\ move $ra, $zero
237 \\
234 \\ lw $25, 0($sp)238 \\ lw $25, 0($sp)
235 \\ lw $4, 4($sp)239 \\ lw $4, 4($sp)
236 \\ jalr $25240 \\ jalr $25
lib/std/os/linux/mips64.zig+4
...@@ -210,6 +210,10 @@ pub fn clone() callconv(.Naked) usize {...@@ -210,6 +210,10 @@ pub fn clone() callconv(.Naked) usize {
210 \\ jr $ra210 \\ jr $ra
211 \\ nop211 \\ nop
212 \\1:212 \\1:
213 \\ .cfi_undefined $ra
214 \\ move $fp, $zero
215 \\ move $ra, $zero
216 \\
213 \\ ld $25, 0($sp)217 \\ ld $25, 0($sp)
214 \\ ld $4, 8($sp)218 \\ ld $4, 8($sp)
215 \\ jalr $25219 \\ jalr $25
lib/std/os/linux/powerpc.zig+20-20
...@@ -133,14 +133,14 @@ pub fn clone() callconv(.Naked) usize {...@@ -133,14 +133,14 @@ pub fn clone() callconv(.Naked) usize {
133 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)133 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
134 // 0 3, 4, 5, 6, 7134 // 0 3, 4, 5, 6, 7
135 asm volatile (135 asm volatile (
136 \\ # store non-volatile regs r30, r31 on stack in order to put our136 \\ # store non-volatile regs r29, r30 on stack in order to put our
137 \\ # start func and its arg there137 \\ # start func and its arg there
138 \\ stwu 30, -16(1)138 \\ stwu 29, -16(1)
139 \\ stw 31, 4(1)139 \\ stw 30, 4(1)
140 \\140 \\
141 \\ # save r3 (func) into r30, and r6(arg) into r31141 \\ # save r3 (func) into r29, and r6(arg) into r30
142 \\ mr 30, 3142 \\ mr 29, 3
143 \\ mr 31, 6143 \\ mr 30, 6
144 \\144 \\
145 \\ # create initial stack frame for new thread145 \\ # create initial stack frame for new thread
146 \\ clrrwi 4, 4, 4146 \\ clrrwi 4, 4, 4
...@@ -167,28 +167,28 @@ pub fn clone() callconv(.Naked) usize {...@@ -167,28 +167,28 @@ pub fn clone() callconv(.Naked) usize {
167 \\ # compare sc result with 0167 \\ # compare sc result with 0
168 \\ cmpwi cr7, 3, 0168 \\ cmpwi cr7, 3, 0
169 \\169 \\
170 \\ # if not 0, jump to end170 \\ # if not 0, restore stack and return
171 \\ bne cr7, 2f171 \\ beq cr7, 2f
172 \\ lwz 29, 0(1)
173 \\ lwz 30, 4(1)
174 \\ addi 1, 1, 16
175 \\ blr
172 \\176 \\
173 \\ #else: we're the child177 \\ #else: we're the child
178 \\ 2:
179 \\ .cfi_undefined lr
180 \\ li 31, 0
181 \\ mtlr 0
182 \\
174 \\ #call funcptr: move arg (d) into r3183 \\ #call funcptr: move arg (d) into r3
175 \\ mr 3, 31184 \\ mr 3, 30
176 \\ #move r30 (funcptr) into CTR reg185 \\ #move r29 (funcptr) into CTR reg
177 \\ mtctr 30186 \\ mtctr 29
178 \\ # call CTR reg187 \\ # call CTR reg
179 \\ bctrl188 \\ bctrl
180 \\ # mov SYS_exit into r0 (the exit param is already in r3)189 \\ # mov SYS_exit into r0 (the exit param is already in r3)
181 \\ li 0, 1190 \\ li 0, 1
182 \\ sc191 \\ sc
183 \\
184 \\ 2:
185 \\
186 \\ # restore stack
187 \\ lwz 30, 0(1)
188 \\ lwz 31, 4(1)
189 \\ addi 1, 1, 16
190 \\
191 \\ blr
192 );192 );
193}193}
194194
lib/std/os/linux/powerpc64.zig+6-1
...@@ -160,7 +160,12 @@ pub fn clone() callconv(.Naked) usize {...@@ -160,7 +160,12 @@ pub fn clone() callconv(.Naked) usize {
160 \\ cmpwi cr7, 3, 0160 \\ cmpwi cr7, 3, 0
161 \\ bnelr cr7161 \\ bnelr cr7
162 \\162 \\
163 \\ # we're the child. call fn(arg)163 \\ # we're the child
164 \\ .cfi_undefined lr
165 \\ li 31, 0
166 \\ mtlr 0
167 \\
168 \\ # call fn(arg)
164 \\ ld 3, 16(1)169 \\ ld 3, 16(1)
165 \\ ld 12, 8(1)170 \\ ld 12, 8(1)
166 \\ mtctr 12171 \\ mtctr 12
lib/std/os/linux/riscv32.zig+5-1
...@@ -120,7 +120,11 @@ pub fn clone() callconv(.Naked) usize {...@@ -120,7 +120,11 @@ pub fn clone() callconv(.Naked) usize {
120 \\ ret120 \\ ret
121 \\121 \\
122 \\ # Child122 \\ # Child
123 \\1: lw a1, 0(sp)123 \\1: .cfi_undefined ra
124 \\ mv fp, zero
125 \\ mv ra, zero
126 \\
127 \\ lw a1, 0(sp)
124 \\ lw a0, 4(sp)128 \\ lw a0, 4(sp)
125 \\ jalr a1129 \\ jalr a1
126 \\130 \\
lib/std/os/linux/riscv64.zig+5-1
...@@ -120,7 +120,11 @@ pub fn clone() callconv(.Naked) usize {...@@ -120,7 +120,11 @@ pub fn clone() callconv(.Naked) usize {
120 \\ ret120 \\ ret
121 \\121 \\
122 \\ # Child122 \\ # Child
123 \\1: ld a1, 0(sp)123 \\1: .cfi_undefined ra
124 \\ mv fp, zero
125 \\ mv ra, zero
126 \\
127 \\ ld a1, 0(sp)
124 \\ ld a0, 8(sp)128 \\ ld a0, 8(sp)
125 \\ jalr a1129 \\ jalr a1
126 \\130 \\
lib/std/os/linux/s390x.zig+6-1
...@@ -133,7 +133,12 @@ pub fn clone() callconv(.Naked) usize {...@@ -133,7 +133,12 @@ pub fn clone() callconv(.Naked) usize {
133 \\ltgr %%r2, %%r2133 \\ltgr %%r2, %%r2
134 \\bnzr %%r14134 \\bnzr %%r14
135 \\135 \\
136 \\# we're the child. call fn(arg)136 \\# we're the child
137 \\.cfi_undefined %%r14
138 \\lghi %%r11, 0
139 \\lghi %%r14, 0
140 \\
141 \\# call fn(arg)
137 \\lg %%r1, 8(%%r15)142 \\lg %%r1, 8(%%r15)
138 \\lg %%r2, 16(%%r15)143 \\lg %%r2, 16(%%r15)
139 \\basr %%r14, %%r1144 \\basr %%r14, %%r1
lib/std/os/linux/sparc64.zig+13-8
...@@ -198,29 +198,34 @@ pub fn clone() callconv(.Naked) usize {...@@ -198,29 +198,34 @@ pub fn clone() callconv(.Naked) usize {
198 \\ mov %%i5, %%o3198 \\ mov %%i5, %%o3
199 \\ ldx [%%fp + 0x8af], %%o4199 \\ ldx [%%fp + 0x8af], %%o4
200 \\ t 0x6d200 \\ t 0x6d
201 \\ bcs,pn %%xcc, 2f201 \\ bcs,pn %%xcc, 1f
202 \\ nop202 \\ nop
203 \\ # The child pid is returned in o0 while o1 tells if this203 \\ # The child pid is returned in o0 while o1 tells if this
204 \\ # process is # the child (=1) or the parent (=0).204 \\ # process is # the child (=1) or the parent (=0).
205 \\ brnz %%o1, 1f205 \\ brnz %%o1, 2f
206 \\ nop206 \\ nop
207 \\ # Parent process, return the child pid207 \\ # Parent process, return the child pid
208 \\ mov %%o0, %%i0208 \\ mov %%o0, %%i0
209 \\ ret209 \\ ret
210 \\ restore210 \\ restore
211 \\1:211 \\1:
212 \\ # Child process, call func(arg)212 \\ # The syscall failed
213 \\ sub %%g0, %%o0, %%i0
214 \\ ret
215 \\ restore
216 \\2:
217 \\ # Child process
218 \\ .cfi_undefined %%i7
219 \\ mov %%g0, %%fp
220 \\ mov %%g0, %%i7
221 \\
222 \\ # call func(arg)
213 \\ mov %%g0, %%fp223 \\ mov %%g0, %%fp
214 \\ call %%g2224 \\ call %%g2
215 \\ mov %%g3, %%o0225 \\ mov %%g3, %%o0
216 \\ # Exit226 \\ # Exit
217 \\ mov 1, %%g1 // SYS_exit227 \\ mov 1, %%g1 // SYS_exit
218 \\ t 0x6d228 \\ t 0x6d
219 \\2:
220 \\ # The syscall failed
221 \\ sub %%g0, %%o0, %%i0
222 \\ ret
223 \\ restore
224 );229 );
225}230}
226231
lib/std/os/linux/x86.zig+11-8
...@@ -148,19 +148,22 @@ pub fn clone() callconv(.Naked) usize {...@@ -148,19 +148,22 @@ pub fn clone() callconv(.Naked) usize {
148 \\ movl $120,%%eax // SYS_clone148 \\ movl $120,%%eax // SYS_clone
149 \\ int $128149 \\ int $128
150 \\ testl %%eax,%%eax150 \\ testl %%eax,%%eax
151 \\ jnz 1f151 \\ jz 1f
152 \\ popl %%eax
153 \\ xorl %%ebp,%%ebp
154 \\ calll *%%eax
155 \\ movl %%eax,%%ebx
156 \\ movl $1,%%eax // SYS_exit
157 \\ int $128
158 \\1:
159 \\ popl %%edi152 \\ popl %%edi
160 \\ popl %%esi153 \\ popl %%esi
161 \\ popl %%ebx154 \\ popl %%ebx
162 \\ popl %%ebp155 \\ popl %%ebp
163 \\ retl156 \\ retl
157 \\
158 \\1:
159 \\ .cfi_undefined %%eip
160 \\ xorl %%ebp,%%ebp
161 \\
162 \\ popl %%eax
163 \\ calll *%%eax
164 \\ movl %%eax,%%ebx
165 \\ movl $1,%%eax // SYS_exit
166 \\ int $128
164 );167 );
165}168}
166169
lib/std/os/linux/x86_64.zig+2
...@@ -116,8 +116,10 @@ pub fn clone() callconv(.Naked) usize {...@@ -116,8 +116,10 @@ pub fn clone() callconv(.Naked) usize {
116 \\ testq %%rax,%%rax116 \\ testq %%rax,%%rax
117 \\ jz 1f117 \\ jz 1f
118 \\ retq118 \\ retq
119 \\
119 \\1: .cfi_undefined %%rip120 \\1: .cfi_undefined %%rip
120 \\ xorl %%ebp,%%ebp121 \\ xorl %%ebp,%%ebp
122 \\
121 \\ popq %%rdi123 \\ popq %%rdi
122 \\ callq *%%r9124 \\ callq *%%r9
123 \\ movl %%eax,%%edi125 \\ movl %%eax,%%edi
lib/std/start.zig+45-6
...@@ -230,6 +230,29 @@ fn _start() callconv(.naked) noreturn {...@@ -230,6 +230,29 @@ fn _start() callconv(.naked) noreturn {
230 );230 );
231 }231 }
232232
233 // This is the first userspace frame. Prevent DWARF-based unwinders from unwinding further. We
234 // prevent FP-based unwinders from unwinding further by zeroing the register further below.
235 asm volatile (switch (native_arch) {
236 .arc => ".cfi_undefined blink",
237 .arm, .armeb, .thumb, .thumbeb => "", // https://github.com/llvm/llvm-project/issues/115891
238 .aarch64, .aarch64_be => ".cfi_undefined lr",
239 .csky => ".cfi_undefined lr",
240 .hexagon => ".cfi_undefined r31",
241 .loongarch32, .loongarch64 => ".cfi_undefined 1",
242 .m68k => ".cfi_undefined pc",
243 .mips, .mipsel, .mips64, .mips64el => ".cfi_undefined $ra",
244 .powerpc, .powerpcle, .powerpc64, .powerpc64le => ".cfi_undefined lr",
245 .riscv32, .riscv64 => if (builtin.zig_backend == .stage2_riscv64)
246 ""
247 else
248 ".cfi_undefined ra",
249 .s390x => ".cfi_undefined %%r14",
250 .sparc, .sparc64 => ".cfi_undefined %%i7",
251 .x86 => ".cfi_undefined %%eip",
252 .x86_64 => ".cfi_undefined %%rip",
253 else => @compileError("unsupported arch"),
254 });
255
233 // Move this to the riscv prong below when this is resolved: https://github.com/ziglang/zig/issues/20918256 // Move this to the riscv prong below when this is resolved: https://github.com/ziglang/zig/issues/20918
234 if (builtin.cpu.arch.isRISCV() and builtin.zig_backend != .stage2_riscv64) asm volatile (257 if (builtin.cpu.arch.isRISCV() and builtin.zig_backend != .stage2_riscv64) asm volatile (
235 \\ .weak __global_pointer$258 \\ .weak __global_pointer$
...@@ -247,7 +270,6 @@ fn _start() callconv(.naked) noreturn {...@@ -247,7 +270,6 @@ fn _start() callconv(.naked) noreturn {
247 // linker explicitly.270 // linker explicitly.
248 asm volatile (switch (native_arch) {271 asm volatile (switch (native_arch) {
249 .x86_64 =>272 .x86_64 =>
250 \\ .cfi_undefined %%rip
251 \\ xorl %%ebp, %%ebp273 \\ xorl %%ebp, %%ebp
252 \\ movq %%rsp, %%rdi274 \\ movq %%rsp, %%rdi
253 \\ andq $-16, %%rsp275 \\ andq $-16, %%rsp
...@@ -279,8 +301,10 @@ fn _start() callconv(.naked) noreturn {...@@ -279,8 +301,10 @@ fn _start() callconv(.naked) noreturn {
279 ,301 ,
280 .arm, .armeb, .thumb, .thumbeb =>302 .arm, .armeb, .thumb, .thumbeb =>
281 // Note that this code must work for Thumb-1.303 // Note that this code must work for Thumb-1.
304 // r7 = FP (local), r11 = FP (unwind)
282 \\ movs v1, #0305 \\ movs v1, #0
283 \\ mov fp, v1306 \\ mov r7, v1
307 \\ mov r11, v1
284 \\ mov lr, v1308 \\ mov lr, v1
285 \\ mov a1, sp309 \\ mov a1, sp
286 \\ subs v1, #16310 \\ subs v1, #16
...@@ -290,20 +314,23 @@ fn _start() callconv(.naked) noreturn {...@@ -290,20 +314,23 @@ fn _start() callconv(.naked) noreturn {
290 ,314 ,
291 .csky =>315 .csky =>
292 // The CSKY ABI assumes that `gb` is set to the address of the GOT in order for316 // The CSKY ABI assumes that `gb` is set to the address of the GOT in order for
293 // position-independent code to work. We depend on this in `std.os.linux.start_pie`317 // position-independent code to work. We depend on this in `std.os.linux.pie` to locate
294 // to locate `_DYNAMIC` as well.318 // `_DYNAMIC` as well.
319 // r8 = FP
295 \\ grs t0, 1f320 \\ grs t0, 1f
296 \\ 1:321 \\ 1:
297 \\ lrw gb, 1b@GOTPC322 \\ lrw gb, 1b@GOTPC
298 \\ addu gb, t0323 \\ addu gb, t0
324 \\ movi r8, 0
299 \\ movi lr, 0325 \\ movi lr, 0
300 \\ mov a0, sp326 \\ mov a0, sp
301 \\ andi sp, sp, -8327 \\ andi sp, sp, -8
302 \\ jmpi %[posixCallMainAndExit]328 \\ jmpi %[posixCallMainAndExit]
303 ,329 ,
304 .hexagon =>330 .hexagon =>
305 // r29 = SP, r30 = FP331 // r29 = SP, r30 = FP, r31 = LR
306 \\ r30 = #0332 \\ r30 = #0
333 \\ r31 = #0
307 \\ r0 = r29334 \\ r0 = r29
308 \\ r29 = and(r29, #-16)335 \\ r29 = and(r29, #-16)
309 \\ memw(r29 + #-8) = r29336 \\ memw(r29 + #-8) = r29
...@@ -312,12 +339,13 @@ fn _start() callconv(.naked) noreturn {...@@ -312,12 +339,13 @@ fn _start() callconv(.naked) noreturn {
312 ,339 ,
313 .loongarch32, .loongarch64 =>340 .loongarch32, .loongarch64 =>
314 \\ move $fp, $zero341 \\ move $fp, $zero
342 \\ move $ra, $zero
315 \\ move $a0, $sp343 \\ move $a0, $sp
316 \\ bstrins.d $sp, $zero, 3, 0344 \\ bstrins.d $sp, $zero, 3, 0
317 \\ b %[posixCallMainAndExit]345 \\ b %[posixCallMainAndExit]
318 ,346 ,
319 .riscv32, .riscv64 =>347 .riscv32, .riscv64 =>
320 \\ li s0, 0348 \\ li fp, 0
321 \\ li ra, 0349 \\ li ra, 0
322 \\ mv a0, sp350 \\ mv a0, sp
323 \\ andi sp, sp, -16351 \\ andi sp, sp, -16
...@@ -371,28 +399,35 @@ fn _start() callconv(.naked) noreturn {...@@ -371,28 +399,35 @@ fn _start() callconv(.naked) noreturn {
371 ,399 ,
372 .powerpc, .powerpcle =>400 .powerpc, .powerpcle =>
373 // Set up the initial stack frame, and clear the back chain pointer.401 // Set up the initial stack frame, and clear the back chain pointer.
402 // r1 = SP, r31 = FP
374 \\ mr 3, 1403 \\ mr 3, 1
375 \\ clrrwi 1, 1, 4404 \\ clrrwi 1, 1, 4
376 \\ li 0, 0405 \\ li 0, 0
377 \\ stwu 1, -16(1)406 \\ stwu 1, -16(1)
378 \\ stw 0, 0(1)407 \\ stw 0, 0(1)
408 \\ li 31, 0
379 \\ mtlr 0409 \\ mtlr 0
380 \\ b %[posixCallMainAndExit]410 \\ b %[posixCallMainAndExit]
381 ,411 ,
382 .powerpc64, .powerpc64le =>412 .powerpc64, .powerpc64le =>
383 // Set up the ToC and initial stack frame, and clear the back chain pointer.413 // Set up the ToC and initial stack frame, and clear the back chain pointer.
414 // r1 = SP, r2 = ToC, r31 = FP
384 \\ addis 2, 12, .TOC. - %[_start]@ha415 \\ addis 2, 12, .TOC. - %[_start]@ha
385 \\ addi 2, 2, .TOC. - %[_start]@l416 \\ addi 2, 2, .TOC. - %[_start]@l
386 \\ mr 3, 1417 \\ mr 3, 1
387 \\ clrrdi 1, 1, 4418 \\ clrrdi 1, 1, 4
388 \\ li 0, 0419 \\ li 0, 0
389 \\ stdu 0, -32(1)420 \\ stdu 0, -32(1)
421 \\ li 31, 0
390 \\ mtlr 0422 \\ mtlr 0
391 \\ b %[posixCallMainAndExit]423 \\ b %[posixCallMainAndExit]
392 \\ nop424 \\ nop
393 ,425 ,
394 .s390x =>426 .s390x =>
395 // Set up the stack frame (register save area and cleared back-chain slot).427 // Set up the stack frame (register save area and cleared back-chain slot).
428 // r11 = FP, r14 = LR, r15 = SP
429 \\ lghi %%r11, 0
430 \\ lghi %%r14, 0
396 \\ lgr %%r2, %%r15431 \\ lgr %%r2, %%r15
397 \\ lghi %%r0, -16432 \\ lghi %%r0, -16
398 \\ ngr %%r15, %%r0433 \\ ngr %%r15, %%r0
...@@ -403,7 +438,9 @@ fn _start() callconv(.naked) noreturn {...@@ -403,7 +438,9 @@ fn _start() callconv(.naked) noreturn {
403 ,438 ,
404 .sparc =>439 .sparc =>
405 // argc is stored after a register window (16 registers * 4 bytes).440 // argc is stored after a register window (16 registers * 4 bytes).
441 // i7 = LR
406 \\ mov %%g0, %%fp442 \\ mov %%g0, %%fp
443 \\ mov %%g0, %%i7
407 \\ add %%sp, 64, %%o0444 \\ add %%sp, 64, %%o0
408 \\ and %%sp, -8, %%sp445 \\ and %%sp, -8, %%sp
409 \\ ba,a %[posixCallMainAndExit]446 \\ ba,a %[posixCallMainAndExit]
...@@ -411,7 +448,9 @@ fn _start() callconv(.naked) noreturn {...@@ -411,7 +448,9 @@ fn _start() callconv(.naked) noreturn {
411 .sparc64 =>448 .sparc64 =>
412 // argc is stored after a register window (16 registers * 8 bytes) plus the stack bias449 // argc is stored after a register window (16 registers * 8 bytes) plus the stack bias
413 // (2047 bytes).450 // (2047 bytes).
451 // i7 = LR
414 \\ mov %%g0, %%fp452 \\ mov %%g0, %%fp
453 \\ mov %%g0, %%i7
415 \\ add %%sp, 2175, %%o0454 \\ add %%sp, 2175, %%o0
416 \\ add %%sp, 2047, %%sp455 \\ add %%sp, 2047, %%sp
417 \\ and %%sp, -16, %%sp456 \\ and %%sp, -16, %%sp
src/Builtin.zig+3
...@@ -2,6 +2,7 @@ target: std.Target,...@@ -2,6 +2,7 @@ target: std.Target,
2zig_backend: std.builtin.CompilerBackend,2zig_backend: std.builtin.CompilerBackend,
3output_mode: std.builtin.OutputMode,3output_mode: std.builtin.OutputMode,
4link_mode: std.builtin.LinkMode,4link_mode: std.builtin.LinkMode,
5unwind_tables: std.builtin.UnwindTables,
5is_test: bool,6is_test: bool,
6single_threaded: bool,7single_threaded: bool,
7link_libc: bool,8link_libc: bool,
...@@ -40,6 +41,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -40,6 +41,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
40 \\41 \\
41 \\pub const output_mode: std.builtin.OutputMode = .{p_};42 \\pub const output_mode: std.builtin.OutputMode = .{p_};
42 \\pub const link_mode: std.builtin.LinkMode = .{p_};43 \\pub const link_mode: std.builtin.LinkMode = .{p_};
44 \\pub const unwind_tables: std.builtin.UnwindTables = .{p_};
43 \\pub const is_test = {};45 \\pub const is_test = {};
44 \\pub const single_threaded = {};46 \\pub const single_threaded = {};
45 \\pub const abi: std.Target.Abi = .{p_};47 \\pub const abi: std.Target.Abi = .{p_};
...@@ -53,6 +55,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -53,6 +55,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
53 std.zig.fmtId(@tagName(zig_backend)),55 std.zig.fmtId(@tagName(zig_backend)),
54 std.zig.fmtId(@tagName(opts.output_mode)),56 std.zig.fmtId(@tagName(opts.output_mode)),
55 std.zig.fmtId(@tagName(opts.link_mode)),57 std.zig.fmtId(@tagName(opts.link_mode)),
58 std.zig.fmtId(@tagName(opts.unwind_tables)),
56 opts.is_test,59 opts.is_test,
57 opts.single_threaded,60 opts.single_threaded,
58 std.zig.fmtId(@tagName(target.abi)),61 std.zig.fmtId(@tagName(target.abi)),
src/Compilation.zig+20-7
...@@ -1261,12 +1261,15 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1261,12 +1261,15 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1261 // The "any" values provided by resolved config only account for1261 // The "any" values provided by resolved config only account for
1262 // explicitly-provided settings. We now make them additionally account1262 // explicitly-provided settings. We now make them additionally account
1263 // for default setting resolution.1263 // for default setting resolution.
1264 const any_unwind_tables = options.config.any_unwind_tables or options.root_mod.unwind_tables;1264 const any_unwind_tables = switch (options.config.any_unwind_tables) {
1265 .none => options.root_mod.unwind_tables,
1266 .sync, .@"async" => |uwt| uwt,
1267 };
1265 const any_non_single_threaded = options.config.any_non_single_threaded or !options.root_mod.single_threaded;1268 const any_non_single_threaded = options.config.any_non_single_threaded or !options.root_mod.single_threaded;
1266 const any_sanitize_thread = options.config.any_sanitize_thread or options.root_mod.sanitize_thread;1269 const any_sanitize_thread = options.config.any_sanitize_thread or options.root_mod.sanitize_thread;
1267 const any_fuzz = options.config.any_fuzz or options.root_mod.fuzz;1270 const any_fuzz = options.config.any_fuzz or options.root_mod.fuzz;
12681271
1269 const link_eh_frame_hdr = options.link_eh_frame_hdr or any_unwind_tables;1272 const link_eh_frame_hdr = options.link_eh_frame_hdr or any_unwind_tables != .none;
1270 const build_id = options.build_id orelse .none;1273 const build_id = options.build_id orelse .none;
12711274
1272 const link_libc = options.config.link_libc;1275 const link_libc = options.config.link_libc;
...@@ -1354,6 +1357,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1354,6 +1357,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1354 cache.hash.add(options.config.pie);1357 cache.hash.add(options.config.pie);
1355 cache.hash.add(options.config.lto);1358 cache.hash.add(options.config.lto);
1356 cache.hash.add(options.config.link_mode);1359 cache.hash.add(options.config.link_mode);
1360 cache.hash.add(options.config.any_unwind_tables);
1357 cache.hash.add(options.function_sections);1361 cache.hash.add(options.function_sections);
1358 cache.hash.add(options.data_sections);1362 cache.hash.add(options.data_sections);
1359 cache.hash.add(link_libc);1363 cache.hash.add(link_libc);
...@@ -5553,10 +5557,17 @@ pub fn addCCArgs(...@@ -5553,10 +5557,17 @@ pub fn addCCArgs(
5553 try argv.append("-Werror=date-time");5557 try argv.append("-Werror=date-time");
5554 }5558 }
55555559
5556 if (mod.unwind_tables) {5560 switch (mod.unwind_tables) {
5557 try argv.append("-funwind-tables");5561 .none => {
5558 } else {5562 try argv.append("-fno-unwind-tables");
5559 try argv.append("-fno-unwind-tables");5563 try argv.append("-fno-asynchronous-unwind-tables");
5564 },
5565 .sync => {
5566 // Need to override Clang's convoluted default logic.
5567 try argv.append("-fno-asynchronous-unwind-tables");
5568 try argv.append("-funwind-tables");
5569 },
5570 .@"async" => try argv.append("-fasynchronous-unwind-tables"),
5560 }5571 }
5561 },5572 },
5562 .shared_library, .ll, .bc, .unknown, .static_library, .object, .def, .zig, .res, .manifest => {},5573 .shared_library, .ll, .bc, .unknown, .static_library, .object, .def, .zig, .res, .manifest => {},
...@@ -6288,6 +6299,7 @@ pub const CrtFileOptions = struct {...@@ -6288,6 +6299,7 @@ pub const CrtFileOptions = struct {
6288 function_sections: ?bool = null,6299 function_sections: ?bool = null,
6289 data_sections: ?bool = null,6300 data_sections: ?bool = null,
6290 omit_frame_pointer: ?bool = null,6301 omit_frame_pointer: ?bool = null,
6302 unwind_tables: ?std.builtin.UnwindTables = null,
6291 pic: ?bool = null,6303 pic: ?bool = null,
6292 no_builtin: ?bool = null,6304 no_builtin: ?bool = null,
6293};6305};
...@@ -6349,7 +6361,8 @@ pub fn build_crt_file(...@@ -6349,7 +6361,8 @@ pub fn build_crt_file(
6349 // Some libcs (e.g. musl) are opinionated about -fomit-frame-pointer.6361 // Some libcs (e.g. musl) are opinionated about -fomit-frame-pointer.
6350 .omit_frame_pointer = options.omit_frame_pointer orelse comp.root_mod.omit_frame_pointer,6362 .omit_frame_pointer = options.omit_frame_pointer orelse comp.root_mod.omit_frame_pointer,
6351 .valgrind = false,6363 .valgrind = false,
6352 .unwind_tables = false,6364 // Some libcs (e.g. MinGW) are opinionated about -funwind-tables.
6365 .unwind_tables = options.unwind_tables orelse .none,
6353 // Some CRT objects (e.g. musl's rcrt1.o and Scrt1.o) are opinionated about PIC.6366 // Some CRT objects (e.g. musl's rcrt1.o and Scrt1.o) are opinionated about PIC.
6354 .pic = options.pic orelse comp.root_mod.pic,6367 .pic = options.pic orelse comp.root_mod.pic,
6355 .optimize_mode = comp.compilerRtOptMode(),6368 .optimize_mode = comp.compilerRtOptMode(),
src/Compilation/Config.zig+14-10
...@@ -12,13 +12,14 @@ link_libunwind: bool,...@@ -12,13 +12,14 @@ link_libunwind: bool,
12/// True if and only if the c_source_files field will have nonzero length when12/// True if and only if the c_source_files field will have nonzero length when
13/// calling Compilation.create.13/// calling Compilation.create.
14any_c_source_files: bool,14any_c_source_files: bool,
15/// This is true if any Module has unwind_tables set explicitly to true. Until15/// This is not `.none` if any `Module` has `unwind_tables` set explicitly to a
16/// Compilation.create is called, it is possible for this to be false while in16/// value other than `.none`. Until `Compilation.create()` is called, it is
17/// fact all Module instances have unwind_tables=true due to the default17/// possible for this to be `.none` while in fact all `Module` instances have
18/// being unwind_tables=true. After Compilation.create is called this will18/// `unwind_tables != .none` due to the default. After `Compilation.create()` is
19/// also take into account the default setting, making this value true if and19/// called, this will also take into account the default setting, making this
20/// only if any Module has unwind_tables set to true.20/// value `.sync` or `.@"async"` if and only if any `Module` has
21any_unwind_tables: bool,21/// `unwind_tables != .none`.
22any_unwind_tables: std.builtin.UnwindTables,
22/// This is true if any Module has single_threaded set explicitly to false. Until23/// This is true if any Module has single_threaded set explicitly to false. Until
23/// Compilation.create is called, it is possible for this to be false while in24/// Compilation.create is called, it is possible for this to be false while in
24/// fact all Module instances have single_threaded=false due to the default25/// fact all Module instances have single_threaded=false due to the default
...@@ -85,7 +86,7 @@ pub const Options = struct {...@@ -85,7 +86,7 @@ pub const Options = struct {
85 any_non_single_threaded: bool = false,86 any_non_single_threaded: bool = false,
86 any_sanitize_thread: bool = false,87 any_sanitize_thread: bool = false,
87 any_fuzz: bool = false,88 any_fuzz: bool = false,
88 any_unwind_tables: bool = false,89 any_unwind_tables: std.builtin.UnwindTables = .none,
89 any_dyn_libs: bool = false,90 any_dyn_libs: bool = false,
90 any_c_source_files: bool = false,91 any_c_source_files: bool = false,
91 any_non_stripped: bool = false,92 any_non_stripped: bool = false,
...@@ -356,8 +357,11 @@ pub fn resolve(options: Options) ResolveError!Config {...@@ -356,8 +357,11 @@ pub fn resolve(options: Options) ResolveError!Config {
356 break :b false;357 break :b false;
357 };358 };
358359
359 const any_unwind_tables = options.any_unwind_tables or360 const any_unwind_tables = b: {
360 link_libunwind or target_util.needUnwindTables(target);361 if (options.any_unwind_tables != .none) break :b options.any_unwind_tables;
362
363 break :b target_util.needUnwindTables(target, link_libunwind, options.any_sanitize_thread);
364 };
361365
362 const link_mode = b: {366 const link_mode = b: {
363 const explicitly_exe_or_dyn_lib = switch (options.output_mode) {367 const explicitly_exe_or_dyn_lib = switch (options.output_mode) {
src/Package/Module.zig+4-3
...@@ -27,7 +27,7 @@ red_zone: bool,...@@ -27,7 +27,7 @@ red_zone: bool,
27sanitize_c: bool,27sanitize_c: bool,
28sanitize_thread: bool,28sanitize_thread: bool,
29fuzz: bool,29fuzz: bool,
30unwind_tables: bool,30unwind_tables: std.builtin.UnwindTables,
31cc_argv: []const []const u8,31cc_argv: []const []const u8,
32/// (SPIR-V) whether to generate a structured control flow graph or not32/// (SPIR-V) whether to generate a structured control flow graph or not
33structured_cfg: bool,33structured_cfg: bool,
...@@ -91,7 +91,7 @@ pub const CreateOptions = struct {...@@ -91,7 +91,7 @@ pub const CreateOptions = struct {
91 /// other number means stack protection with that buffer size.91 /// other number means stack protection with that buffer size.
92 stack_protector: ?u32 = null,92 stack_protector: ?u32 = null,
93 red_zone: ?bool = null,93 red_zone: ?bool = null,
94 unwind_tables: ?bool = null,94 unwind_tables: ?std.builtin.UnwindTables = null,
95 sanitize_c: ?bool = null,95 sanitize_c: ?bool = null,
96 sanitize_thread: ?bool = null,96 sanitize_thread: ?bool = null,
97 fuzz: ?bool = null,97 fuzz: ?bool = null,
...@@ -112,7 +112,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {...@@ -112,7 +112,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
112 if (options.inherited.sanitize_thread == true) assert(options.global.any_sanitize_thread);112 if (options.inherited.sanitize_thread == true) assert(options.global.any_sanitize_thread);
113 if (options.inherited.fuzz == true) assert(options.global.any_fuzz);113 if (options.inherited.fuzz == true) assert(options.global.any_fuzz);
114 if (options.inherited.single_threaded == false) assert(options.global.any_non_single_threaded);114 if (options.inherited.single_threaded == false) assert(options.global.any_non_single_threaded);
115 if (options.inherited.unwind_tables == true) assert(options.global.any_unwind_tables);115 if (options.inherited.unwind_tables) |uwt| if (uwt != .none) assert(options.global.any_unwind_tables != .none);
116 if (options.inherited.error_tracing == true) assert(options.global.any_error_tracing);116 if (options.inherited.error_tracing == true) assert(options.global.any_error_tracing);
117117
118 const resolved_target = options.inherited.resolved_target orelse options.parent.?.resolved_target;118 const resolved_target = options.inherited.resolved_target orelse options.parent.?.resolved_target;
...@@ -382,6 +382,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {...@@ -382,6 +382,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
382 .zig_backend = zig_backend,382 .zig_backend = zig_backend,
383 .output_mode = options.global.output_mode,383 .output_mode = options.global.output_mode,
384 .link_mode = options.global.link_mode,384 .link_mode = options.global.link_mode,
385 .unwind_tables = options.global.any_unwind_tables,
385 .is_test = options.global.is_test,386 .is_test = options.global.is_test,
386 .single_threaded = single_threaded,387 .single_threaded = single_threaded,
387 .link_libc = options.global.link_libc,388 .link_libc = options.global.link_libc,
src/arch/riscv64/CodeGen.zig+4
...@@ -8442,6 +8442,10 @@ fn failSymbol(func: *Func, comptime format: []const u8, args: anytype) InnerErro...@@ -8442,6 +8442,10 @@ fn failSymbol(func: *Func, comptime format: []const u8, args: anytype) InnerErro
8442}8442}
84438443
8444fn parseRegName(name: []const u8) ?Register {8444fn parseRegName(name: []const u8) ?Register {
8445 // The `fp` alias for `s0` is awkward to fit into the current `Register` scheme, so for now we
8446 // special-case it here.
8447 if (std.mem.eql(u8, name, "fp")) return .s0;
8448
8445 return std.meta.stringToEnum(Register, name);8449 return std.meta.stringToEnum(Register, name);
8446}8450}
84478451
src/clang_options_data.zig+16-2
...@@ -2757,7 +2757,14 @@ flagpd1("fast"),...@@ -2757,7 +2757,14 @@ flagpd1("fast"),
2757flagpd1("fastcp"),2757flagpd1("fastcp"),
2758flagpd1("fastf"),2758flagpd1("fastf"),
2759flagpd1("fasync-exceptions"),2759flagpd1("fasync-exceptions"),
2760flagpd1("fasynchronous-unwind-tables"),2760.{
2761 .name = "fasynchronous-unwind-tables",
2762 .syntax = .flag,
2763 .zig_equivalent = .asynchronous_unwind_tables,
2764 .pd1 = true,
2765 .pd2 = false,
2766 .psl = false,
2767},
2761flagpd1("fauto-import"),2768flagpd1("fauto-import"),
2762flagpd1("fauto-profile"),2769flagpd1("fauto-profile"),
2763flagpd1("fauto-profile-accurate"),2770flagpd1("fauto-profile-accurate"),
...@@ -3247,7 +3254,14 @@ flagpd1("fno-assume-sane-operator-new"),...@@ -3247,7 +3254,14 @@ flagpd1("fno-assume-sane-operator-new"),
3247flagpd1("fno-assume-unique-vtables"),3254flagpd1("fno-assume-unique-vtables"),
3248flagpd1("fno-assumptions"),3255flagpd1("fno-assumptions"),
3249flagpd1("fno-async-exceptions"),3256flagpd1("fno-async-exceptions"),
3250flagpd1("fno-asynchronous-unwind-tables"),3257.{
3258 .name = "fno-asynchronous-unwind-tables",
3259 .syntax = .flag,
3260 .zig_equivalent = .no_asynchronous_unwind_tables,
3261 .pd1 = true,
3262 .pd2 = false,
3263 .psl = false,
3264},
3251flagpd1("fno-auto-import"),3265flagpd1("fno-auto-import"),
3252flagpd1("fno-auto-profile"),3266flagpd1("fno-auto-profile"),
3253flagpd1("fno-auto-profile-accurate"),3267flagpd1("fno-auto-profile-accurate"),
src/codegen/llvm.zig+5-2
...@@ -3141,8 +3141,11 @@ pub const Object = struct {...@@ -3141,8 +3141,11 @@ pub const Object = struct {
3141 } }, &o.builder);3141 } }, &o.builder);
3142 }3142 }
3143 try attributes.addFnAttr(.nounwind, &o.builder);3143 try attributes.addFnAttr(.nounwind, &o.builder);
3144 if (owner_mod.unwind_tables) {3144 if (owner_mod.unwind_tables != .none) {
3145 try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder);3145 try attributes.addFnAttr(
3146 .{ .uwtable = if (owner_mod.unwind_tables == .@"async") .@"async" else .sync },
3147 &o.builder,
3148 );
3146 }3149 }
3147 if (owner_mod.no_builtin) {3150 if (owner_mod.no_builtin) {
3148 // The intent here is for compiler-rt and libc functions to not generate3151 // The intent here is for compiler-rt and libc functions to not generate
src/libcxx.zig+6-3
...@@ -397,7 +397,6 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -397,7 +397,6 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
397397
398 const optimize_mode = comp.compilerRtOptMode();398 const optimize_mode = comp.compilerRtOptMode();
399 const strip = comp.compilerRtStrip();399 const strip = comp.compilerRtStrip();
400 const unwind_tables = true;
401400
402 const config = Compilation.Config.resolve(.{401 const config = Compilation.Config.resolve(.{
403 .output_mode = output_mode,402 .output_mode = output_mode,
...@@ -409,7 +408,6 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -409,7 +408,6 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
409 .root_optimize_mode = optimize_mode,408 .root_optimize_mode = optimize_mode,
410 .root_strip = strip,409 .root_strip = strip,
411 .link_libc = true,410 .link_libc = true,
412 .any_unwind_tables = unwind_tables,
413 .lto = comp.config.lto,411 .lto = comp.config.lto,
414 .any_sanitize_thread = comp.config.any_sanitize_thread,412 .any_sanitize_thread = comp.config.any_sanitize_thread,
415 }) catch |err| {413 }) catch |err| {
...@@ -440,7 +438,12 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -440,7 +438,12 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
440 .valgrind = false,438 .valgrind = false,
441 .optimize_mode = optimize_mode,439 .optimize_mode = optimize_mode,
442 .structured_cfg = comp.root_mod.structured_cfg,440 .structured_cfg = comp.root_mod.structured_cfg,
443 .unwind_tables = unwind_tables,441 // See the `-fno-exceptions` logic for WASI.
442 // The old 32-bit x86 variant of SEH doesn't use tables.
443 .unwind_tables = if (target.os.tag == .wasi or (target.cpu.arch == .x86 and target.os.tag == .windows))
444 .none
445 else
446 .@"async",
444 .pic = comp.root_mod.pic,447 .pic = comp.root_mod.pic,
445 },448 },
446 .global = config,449 .global = config,
src/libunwind.zig+2-1
...@@ -65,7 +65,8 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -65,7 +65,8 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
65 .sanitize_c = false,65 .sanitize_c = false,
66 .sanitize_thread = false,66 .sanitize_thread = false,
67 // necessary so that libunwind can unwind through its own stack frames67 // necessary so that libunwind can unwind through its own stack frames
68 .unwind_tables = true,68 // The old 32-bit x86 variant of SEH doesn't use tables.
69 .unwind_tables = if (target.cpu.arch == .x86 and target.os.tag == .windows) .none else .@"async",
69 .pic = if (target_util.supports_fpic(target)) true else null,70 .pic = if (target_util.supports_fpic(target)) true else null,
70 .optimize_mode = comp.compilerRtOptMode(),71 .optimize_mode = comp.compilerRtOptMode(),
71 },72 },
src/main.zig+46-8
...@@ -510,6 +510,7 @@ const usage_build_generic =...@@ -510,6 +510,7 @@ const usage_build_generic =
510 \\ -ffuzz Enable fuzz testing instrumentation510 \\ -ffuzz Enable fuzz testing instrumentation
511 \\ -fno-fuzz Disable fuzz testing instrumentation511 \\ -fno-fuzz Disable fuzz testing instrumentation
512 \\ -funwind-tables Always produce unwind table entries for all functions512 \\ -funwind-tables Always produce unwind table entries for all functions
513 \\ -fasync-unwind-tables Always produce asynchronous unwind table entries for all functions
513 \\ -fno-unwind-tables Never produce unwind table entries514 \\ -fno-unwind-tables Never produce unwind table entries
514 \\ -ferror-tracing Enable error tracing in ReleaseFast mode515 \\ -ferror-tracing Enable error tracing in ReleaseFast mode
515 \\ -fno-error-tracing Disable error tracing in Debug and ReleaseSafe mode516 \\ -fno-error-tracing Disable error tracing in Debug and ReleaseSafe mode
...@@ -1385,9 +1386,11 @@ fn buildOutputType(...@@ -1385,9 +1386,11 @@ fn buildOutputType(
1385 } else if (mem.eql(u8, arg, "-fno-lto")) {1386 } else if (mem.eql(u8, arg, "-fno-lto")) {
1386 create_module.opts.lto = false;1387 create_module.opts.lto = false;
1387 } else if (mem.eql(u8, arg, "-funwind-tables")) {1388 } else if (mem.eql(u8, arg, "-funwind-tables")) {
1388 mod_opts.unwind_tables = true;1389 mod_opts.unwind_tables = .sync;
1390 } else if (mem.eql(u8, arg, "-fasync-unwind-tables")) {
1391 mod_opts.unwind_tables = .@"async";
1389 } else if (mem.eql(u8, arg, "-fno-unwind-tables")) {1392 } else if (mem.eql(u8, arg, "-fno-unwind-tables")) {
1390 mod_opts.unwind_tables = false;1393 mod_opts.unwind_tables = .none;
1391 } else if (mem.eql(u8, arg, "-fstack-check")) {1394 } else if (mem.eql(u8, arg, "-fstack-check")) {
1392 mod_opts.stack_check = true;1395 mod_opts.stack_check = true;
1393 } else if (mem.eql(u8, arg, "-fno-stack-check")) {1396 } else if (mem.eql(u8, arg, "-fno-stack-check")) {
...@@ -1973,8 +1976,27 @@ fn buildOutputType(...@@ -1973,8 +1976,27 @@ fn buildOutputType(
1973 }1976 }
1974 },1977 },
1975 .no_stack_protector => mod_opts.stack_protector = 0,1978 .no_stack_protector => mod_opts.stack_protector = 0,
1976 .unwind_tables => mod_opts.unwind_tables = true,1979 // The way these unwind table options are processed in GCC and Clang is crazy
1977 .no_unwind_tables => mod_opts.unwind_tables = false,1980 // convoluted, and we also don't know the target triple here, so this is all
1981 // best-effort.
1982 .unwind_tables => if (mod_opts.unwind_tables) |uwt| switch (uwt) {
1983 .none => {
1984 mod_opts.unwind_tables = .sync;
1985 },
1986 .sync, .@"async" => {},
1987 } else {
1988 mod_opts.unwind_tables = .sync;
1989 },
1990 .no_unwind_tables => mod_opts.unwind_tables = .none,
1991 .asynchronous_unwind_tables => mod_opts.unwind_tables = .@"async",
1992 .no_asynchronous_unwind_tables => if (mod_opts.unwind_tables) |uwt| switch (uwt) {
1993 .none, .sync => {},
1994 .@"async" => {
1995 mod_opts.unwind_tables = .sync;
1996 },
1997 } else {
1998 mod_opts.unwind_tables = .sync;
1999 },
1978 .nostdlib => {2000 .nostdlib => {
1979 create_module.opts.ensure_libc_on_non_freestanding = false;2001 create_module.opts.ensure_libc_on_non_freestanding = false;
1980 create_module.opts.ensure_libcpp_on_non_freestanding = false;2002 create_module.opts.ensure_libcpp_on_non_freestanding = false;
...@@ -2788,8 +2810,15 @@ fn buildOutputType(...@@ -2788,8 +2810,15 @@ fn buildOutputType(
2788 create_module.opts.any_sanitize_thread = true;2810 create_module.opts.any_sanitize_thread = true;
2789 if (mod_opts.fuzz == true)2811 if (mod_opts.fuzz == true)
2790 create_module.opts.any_fuzz = true;2812 create_module.opts.any_fuzz = true;
2791 if (mod_opts.unwind_tables == true)2813 if (mod_opts.unwind_tables) |uwt| switch (uwt) {
2792 create_module.opts.any_unwind_tables = true;2814 .none => {},
2815 .sync => if (create_module.opts.any_unwind_tables == .none) {
2816 create_module.opts.any_unwind_tables = .sync;
2817 },
2818 .@"async" => {
2819 create_module.opts.any_unwind_tables = .@"async";
2820 },
2821 };
2793 if (mod_opts.strip == false)2822 if (mod_opts.strip == false)
2794 create_module.opts.any_non_stripped = true;2823 create_module.opts.any_non_stripped = true;
2795 if (mod_opts.error_tracing == true)2824 if (mod_opts.error_tracing == true)
...@@ -5713,6 +5742,8 @@ pub const ClangArgIterator = struct {...@@ -5713,6 +5742,8 @@ pub const ClangArgIterator = struct {
5713 no_lto,5742 no_lto,
5714 unwind_tables,5743 unwind_tables,
5715 no_unwind_tables,5744 no_unwind_tables,
5745 asynchronous_unwind_tables,
5746 no_asynchronous_unwind_tables,
5716 nostdlib,5747 nostdlib,
5717 nostdlib_cpp,5748 nostdlib_cpp,
5718 shared,5749 shared,
...@@ -7435,8 +7466,15 @@ fn handleModArg(...@@ -7435,8 +7466,15 @@ fn handleModArg(
7435 create_module.opts.any_sanitize_thread = true;7466 create_module.opts.any_sanitize_thread = true;
7436 if (mod_opts.fuzz == true)7467 if (mod_opts.fuzz == true)
7437 create_module.opts.any_fuzz = true;7468 create_module.opts.any_fuzz = true;
7438 if (mod_opts.unwind_tables == true)7469 if (mod_opts.unwind_tables) |uwt| switch (uwt) {
7439 create_module.opts.any_unwind_tables = true;7470 .none => {},
7471 .sync => if (create_module.opts.any_unwind_tables == .none) {
7472 create_module.opts.any_unwind_tables = .sync;
7473 },
7474 .@"async" => {
7475 create_module.opts.any_unwind_tables = .@"async";
7476 },
7477 };
7440 if (mod_opts.strip == false)7478 if (mod_opts.strip == false)
7441 create_module.opts.any_non_stripped = true;7479 create_module.opts.any_non_stripped = true;
7442 if (mod_opts.error_tracing == true)7480 if (mod_opts.error_tracing == true)
src/mingw.zig+13-4
...@@ -24,6 +24,10 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -24,6 +24,10 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
24 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);24 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
25 defer arena_allocator.deinit();25 defer arena_allocator.deinit();
26 const arena = arena_allocator.allocator();26 const arena = arena_allocator.allocator();
27 const target = comp.getTarget();
28
29 // The old 32-bit x86 variant of SEH doesn't use tables.
30 const unwind_tables: std.builtin.UnwindTables = if (target.cpu.arch != .x86) .@"async" else .none;
2731
28 switch (crt_file) {32 switch (crt_file) {
29 .crt2_o => {33 .crt2_o => {
...@@ -41,7 +45,9 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -41,7 +45,9 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
41 .owner = undefined,45 .owner = undefined,
42 },46 },
43 };47 };
44 return comp.build_crt_file("crt2", .Obj, .@"mingw-w64 crt2.o", prog_node, &files, .{});48 return comp.build_crt_file("crt2", .Obj, .@"mingw-w64 crt2.o", prog_node, &files, .{
49 .unwind_tables = unwind_tables,
50 });
45 },51 },
4652
47 .dllcrt2_o => {53 .dllcrt2_o => {
...@@ -56,7 +62,9 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -56,7 +62,9 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
56 .owner = undefined,62 .owner = undefined,
57 },63 },
58 };64 };
59 return comp.build_crt_file("dllcrt2", .Obj, .@"mingw-w64 dllcrt2.o", prog_node, &files, .{});65 return comp.build_crt_file("dllcrt2", .Obj, .@"mingw-w64 dllcrt2.o", prog_node, &files, .{
66 .unwind_tables = unwind_tables,
67 });
60 },68 },
6169
62 .mingw32_lib => {70 .mingw32_lib => {
...@@ -73,7 +81,6 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -73,7 +81,6 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
73 .owner = undefined,81 .owner = undefined,
74 });82 });
75 }83 }
76 const target = comp.getTarget();
77 if (target.cpu.arch == .x86 or target.cpu.arch == .x86_64) {84 if (target.cpu.arch == .x86 or target.cpu.arch == .x86_64) {
78 for (mingw32_x86_src) |dep| {85 for (mingw32_x86_src) |dep| {
79 try c_source_files.append(.{86 try c_source_files.append(.{
...@@ -118,7 +125,9 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -118,7 +125,9 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
118 } else {125 } else {
119 @panic("unsupported arch");126 @panic("unsupported arch");
120 }127 }
121 return comp.build_crt_file("mingw32", .Lib, .@"mingw-w64 mingw32.lib", prog_node, c_source_files.items, .{});128 return comp.build_crt_file("mingw32", .Lib, .@"mingw-w64 mingw32.lib", prog_node, c_source_files.items, .{
129 .unwind_tables = unwind_tables,
130 });
122 },131 },
123 }132 }
124}133}
src/target.zig+11-2
...@@ -4,6 +4,7 @@ const assert = std.debug.assert;...@@ -4,6 +4,7 @@ const assert = std.debug.assert;
4const Type = @import("Type.zig");4const Type = @import("Type.zig");
5const AddressSpace = std.builtin.AddressSpace;5const AddressSpace = std.builtin.AddressSpace;
6const Alignment = @import("InternPool.zig").Alignment;6const Alignment = @import("InternPool.zig").Alignment;
7const Compilation = @import("Compilation.zig");
7const Feature = @import("Zcu.zig").Feature;8const Feature = @import("Zcu.zig").Feature;
89
9pub const default_stack_protector_buffer_size = 4;10pub const default_stack_protector_buffer_size = 4;
...@@ -408,8 +409,16 @@ pub fn clangSupportsNoImplicitFloatArg(target: std.Target) bool {...@@ -408,8 +409,16 @@ pub fn clangSupportsNoImplicitFloatArg(target: std.Target) bool {
408 };409 };
409}410}
410411
411pub fn needUnwindTables(target: std.Target) bool {412pub fn needUnwindTables(target: std.Target, libunwind: bool, libtsan: bool) std.builtin.UnwindTables {
412 return target.os.tag == .windows or target.isDarwin() or std.debug.Dwarf.abi.supportsUnwinding(target);413 if (target.os.tag == .windows) {
414 // The old 32-bit x86 variant of SEH doesn't use tables.
415 return if (target.cpu.arch != .x86) .@"async" else .none;
416 }
417 if (target.os.tag.isDarwin()) return .@"async";
418 if (libunwind) return .@"async";
419 if (libtsan) return .@"async";
420 if (std.debug.Dwarf.abi.supportsUnwinding(target)) return .@"async";
421 return .none;
413}422}
414423
415pub fn defaultAddressSpace(424pub fn defaultAddressSpace(
test/standalone/stack_iterator/build.zig+3-3
...@@ -23,7 +23,7 @@ pub fn build(b: *std.Build) void {...@@ -23,7 +23,7 @@ pub fn build(b: *std.Build) void {
23 .root_source_file = b.path("unwind.zig"),23 .root_source_file = b.path("unwind.zig"),
24 .target = target,24 .target = target,
25 .optimize = optimize,25 .optimize = optimize,
26 .unwind_tables = if (target.result.isDarwin()) true else null,26 .unwind_tables = if (target.result.isDarwin()) .@"async" else null,
27 .omit_frame_pointer = false,27 .omit_frame_pointer = false,
28 });28 });
2929
...@@ -46,7 +46,7 @@ pub fn build(b: *std.Build) void {...@@ -46,7 +46,7 @@ pub fn build(b: *std.Build) void {
46 .root_source_file = b.path("unwind.zig"),46 .root_source_file = b.path("unwind.zig"),
47 .target = target,47 .target = target,
48 .optimize = optimize,48 .optimize = optimize,
49 .unwind_tables = true,49 .unwind_tables = .@"async",
50 .omit_frame_pointer = true,50 .omit_frame_pointer = true,
51 });51 });
5252
...@@ -85,7 +85,7 @@ pub fn build(b: *std.Build) void {...@@ -85,7 +85,7 @@ pub fn build(b: *std.Build) void {
85 .root_source_file = b.path("shared_lib_unwind.zig"),85 .root_source_file = b.path("shared_lib_unwind.zig"),
86 .target = target,86 .target = target,
87 .optimize = optimize,87 .optimize = optimize,
88 .unwind_tables = if (target.result.isDarwin()) true else null,88 .unwind_tables = if (target.result.isDarwin()) .@"async" else null,
89 .omit_frame_pointer = true,89 .omit_frame_pointer = true,
90 });90 });
9191
tools/update_clang_options.zig+8
...@@ -110,6 +110,14 @@ const known_options = [_]KnownOpt{...@@ -110,6 +110,14 @@ const known_options = [_]KnownOpt{
110 .name = "fno-unwind-tables",110 .name = "fno-unwind-tables",
111 .ident = "no_unwind_tables",111 .ident = "no_unwind_tables",
112 },112 },
113 .{
114 .name = "fasynchronous-unwind-tables",
115 .ident = "asynchronous_unwind_tables",
116 },
117 .{
118 .name = "fno-asynchronous-unwind-tables",
119 .ident = "no_asynchronous_unwind_tables",
120 },
113 .{121 .{
114 .name = "nolibc",122 .name = "nolibc",
115 .ident = "nostdlib",123 .ident = "nostdlib",