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:
2424 // parent
2525 ret
2626 // child
271: ldp x1,x0,[sp],#16
271: mov fp, 0
28 ldp x1,x0,[sp],#16
2829 blr x1
2930 mov x8,#93 // SYS_exit
3031 svc #0
lib/libc/musl/src/thread/arm/clone.s+2-1
......@@ -19,7 +19,8 @@ __clone:
1919 ldmfd sp!,{r4,r5,r6,r7}
2020 bx lr
2121
221: mov r0,r6
221: mov fp,#0
23 mov r0,r6
2324 bl 3f
24252: mov r7,#1
2526 svc 0
lib/libc/musl/src/thread/i386/clone.s+8-9
......@@ -30,9 +30,15 @@ __clone:
3030 mov 8(%ebp),%ebp
3131 int $128
3232 test %eax,%eax
33 jnz 1f
33 jz 1f
34 add $16,%esp
35 pop %edi
36 pop %esi
37 pop %ebx
38 pop %ebp
39 ret
3440
35 mov %ebp,%eax
411: mov %ebp,%eax
3642 xor %ebp,%ebp
3743 call *%eax
3844 mov %eax,%ebx
......@@ -40,10 +46,3 @@ __clone:
4046 inc %eax
4147 int $128
4248 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:
2222 beqz $a0, 1f # whether child process
2323 jirl $zero, $ra, 0 # parent process return
24241:
25 move $fp, $zero
2526 ld.d $t8, $sp, 0 # function pointer
2627 ld.d $a0, $sp, 8 # argument pointer
2728 jirl $ra, $t8, 0 # call the user's function
lib/libc/musl/src/thread/m68k/clone.s+2-1
......@@ -18,7 +18,8 @@ __clone:
1818 beq 1f
1919 movem.l (%sp)+,%d2-%d5
2020 rts
211: move.l %a1,-(%sp)
211: suba.l %%fp,%%fp
22 move.l %a1,-(%sp)
2223 jsr (%a0)
2324 move.l #1,%d0
2425 trap #0
lib/libc/musl/src/thread/microblaze/clone.s+2-1
......@@ -22,7 +22,8 @@ __clone:
2222 rtsd r15, 8
2323 nop
2424
251: lwi r3, r1, 0
251: add r19, r0, r0
26 lwi r3, r1, 0
2627 lwi r5, r1, 4
2728 brald r15, r3
2829 nop
lib/libc/musl/src/thread/mips/clone.s+2-1
......@@ -27,7 +27,8 @@ __clone:
2727 addu $sp, $sp, 16
2828 jr $ra
2929 nop
301: lw $25, 0($sp)
301: move $fp, $0
31 lw $25, 0($sp)
3132 lw $4, 4($sp)
3233 jalr $25
3334 nop
lib/libc/musl/src/thread/mips64/clone.s+2-1
......@@ -25,7 +25,8 @@ __clone:
2525 nop
2626 jr $ra
2727 nop
281: ld $25, 0($sp) # function pointer
281: move $fp, $0
29 ld $25, 0($sp) # function pointer
2930 ld $4, 8($sp) # argument pointer
3031 jalr $25 # call the user's function
3132 nop
lib/libc/musl/src/thread/mipsn32/clone.s+2-1
......@@ -25,7 +25,8 @@ __clone:
2525 nop
2626 jr $ra
2727 nop
281: lw $25, 0($sp) # function pointer
281: move $fp, $0
29 lw $25, 0($sp) # function pointer
2930 lw $4, 4($sp) # argument pointer
3031 jalr $25 # call the user's function
3132 nop
lib/libc/musl/src/thread/or1k/clone.s+2-1
......@@ -23,7 +23,8 @@ __clone:
2323 l.jr r9
2424 l.nop
2525
261: l.lwz r11, 0(r1)
261: l.ori r2, r0, 0
27 l.lwz r11, 0(r1)
2728 l.jalr r11
2829 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)
4848# compare sc result with 0
4949cmpwi cr7, 3, 0
5050
51# if not 0, jump to end
52bne cr7, 2f
51# if not 0, restore stack and return
52beq cr7, 2f
5353
54lwz 30, 0(1)
55lwz 31, 4(1)
56addi 1, 1, 16
57
58blr
59
602:
5461#else: we're the child
5562#call funcptr: move arg (d) into r3
5663mr 3, 31
......@@ -61,13 +68,3 @@ bctrl
6168# mov SYS_exit into r0 (the exit param is already in r3)
6269li 0, 1
6370sc
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:
1515 mov %rcx,(%rsi)
1616 syscall
1717 test %eax,%eax
18 jnz 1f
19 xor %ebp,%ebp
18 jz 1f
19 ret
201: xor %ebp,%ebp
2021 pop %rdi
2122 call *%r9
2223 mov %eax,%edi
2324 movl $0x4000003c,%eax /* SYS_exit */
2425 syscall
2526 hlt
261: ret
lib/libc/musl/src/thread/x86_64/clone.s+3-3
......@@ -16,8 +16,9 @@ __clone:
1616 mov %rcx,(%rsi)
1717 syscall
1818 test %eax,%eax
19 jnz 1f
20 xor %ebp,%ebp
19 jz 1f
20 ret
211: xor %ebp,%ebp
2122 pop %rdi
2223 call *%r9
2324 mov %eax,%edi
......@@ -25,4 +26,3 @@ __clone:
2526 mov $60,%al
2627 syscall
2728 hlt
281: ret
lib/std/Build.zig+5-5
......@@ -706,7 +706,7 @@ pub const ExecutableOptions = struct {
706706 single_threaded: ?bool = null,
707707 pic: ?bool = null,
708708 strip: ?bool = null,
709 unwind_tables: ?bool = null,
709 unwind_tables: ?std.builtin.UnwindTables = null,
710710 omit_frame_pointer: ?bool = null,
711711 sanitize_thread: ?bool = null,
712712 error_tracing: ?bool = null,
......@@ -762,7 +762,7 @@ pub const ObjectOptions = struct {
762762 single_threaded: ?bool = null,
763763 pic: ?bool = null,
764764 strip: ?bool = null,
765 unwind_tables: ?bool = null,
765 unwind_tables: ?std.builtin.UnwindTables = null,
766766 omit_frame_pointer: ?bool = null,
767767 sanitize_thread: ?bool = null,
768768 error_tracing: ?bool = null,
......@@ -810,7 +810,7 @@ pub const SharedLibraryOptions = struct {
810810 single_threaded: ?bool = null,
811811 pic: ?bool = null,
812812 strip: ?bool = null,
813 unwind_tables: ?bool = null,
813 unwind_tables: ?std.builtin.UnwindTables = null,
814814 omit_frame_pointer: ?bool = null,
815815 sanitize_thread: ?bool = null,
816816 error_tracing: ?bool = null,
......@@ -867,7 +867,7 @@ pub const StaticLibraryOptions = struct {
867867 single_threaded: ?bool = null,
868868 pic: ?bool = null,
869869 strip: ?bool = null,
870 unwind_tables: ?bool = null,
870 unwind_tables: ?std.builtin.UnwindTables = null,
871871 omit_frame_pointer: ?bool = null,
872872 sanitize_thread: ?bool = null,
873873 error_tracing: ?bool = null,
......@@ -919,7 +919,7 @@ pub const TestOptions = struct {
919919 single_threaded: ?bool = null,
920920 pic: ?bool = null,
921921 strip: ?bool = null,
922 unwind_tables: ?bool = null,
922 unwind_tables: ?std.builtin.UnwindTables = null,
923923 omit_frame_pointer: ?bool = null,
924924 sanitize_thread: ?bool = null,
925925 error_tracing: ?bool = null,
lib/std/Build/Module.zig+10-3
......@@ -22,7 +22,7 @@ frameworks: std.StringArrayHashMapUnmanaged(LinkFrameworkOptions),
2222link_objects: std.ArrayListUnmanaged(LinkObject),
2323
2424strip: ?bool,
25unwind_tables: ?bool,
25unwind_tables: ?std.builtin.UnwindTables,
2626single_threaded: ?bool,
2727stack_protector: ?bool,
2828stack_check: ?bool,
......@@ -218,7 +218,7 @@ pub const CreateOptions = struct {
218218 link_libcpp: ?bool = null,
219219 single_threaded: ?bool = null,
220220 strip: ?bool = null,
221 unwind_tables: ?bool = null,
221 unwind_tables: ?std.builtin.UnwindTables = null,
222222 dwarf_format: ?std.dwarf.Format = null,
223223 code_model: std.builtin.CodeModel = .default,
224224 stack_protector: ?bool = null,
......@@ -675,7 +675,6 @@ pub fn appendZigProcessFlags(
675675 const b = m.owner;
676676
677677 try addFlag(zig_args, m.strip, "-fstrip", "-fno-strip");
678 try addFlag(zig_args, m.unwind_tables, "-funwind-tables", "-fno-unwind-tables");
679678 try addFlag(zig_args, m.single_threaded, "-fsingle-threaded", "-fno-single-threaded");
680679 try addFlag(zig_args, m.stack_check, "-fstack-check", "-fno-stack-check");
681680 try addFlag(zig_args, m.stack_protector, "-fstack-protector", "-fno-stack-protector");
......@@ -695,6 +694,14 @@ pub fn appendZigProcessFlags(
695694 });
696695 }
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
698705 try zig_args.ensureUnusedCapacity(1);
699706 if (m.optimize) |optimize| switch (optimize) {
700707 .Debug => zig_args.appendAssumeCapacity("-ODebug"),
lib/std/builtin.zig+8
......@@ -804,6 +804,14 @@ pub const LinkMode = enum {
804804 dynamic,
805805};
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
807815/// This data structure is used by the Zig language code generation and
808816/// therefore must be kept in sync with the compiler implementation.
809817pub const WasiExecModel = enum {
lib/std/os/linux/aarch64.zig+6-1
......@@ -120,8 +120,13 @@ pub fn clone() callconv(.Naked) usize {
120120 \\ cbz x0,1f
121121 \\ // parent
122122 \\ ret
123 \\
123124 \\ // child
124 \\1: ldp x1,x0,[sp],#16
125 \\1: .cfi_undefined lr
126 \\ mov fp, 0
127 \\ mov lr, 0
128 \\
129 \\ ldp x1,x0,[sp],#16
125130 \\ blr x1
126131 \\ mov x8,#93 // SYS_exit
127132 \\ svc #0
lib/std/os/linux/arm.zig+8-3
......@@ -120,11 +120,16 @@ pub fn clone() callconv(.Naked) usize {
120120 \\ ldmfd sp!,{r4,r5,r6,r7}
121121 \\ bx lr
122122 \\
123 \\1: mov r0,r6
123 \\ // 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
124129 \\ bl 3f
125 \\2: mov r7,#1 // SYS_exit
130 \\ mov r7,#1 // SYS_exit
126131 \\ svc 0
127 \\ b 2b
132 \\
128133 \\3: bx r5
129134 );
130135}
lib/std/os/linux/hexagon.zig+4
......@@ -118,6 +118,10 @@ pub fn clone() callconv(.Naked) usize {
118118 \\ p0 = cmp.eq(r0, #0)
119119 \\ if (!p0) dealloc_return
120120 \\
121 \\ .cfi_undefined r31
122 \\ r30 = #0
123 \\ r31 = #0
124 \\
121125 \\ r0 = r10
122126 \\ callr r11
123127 \\
lib/std/os/linux/loongarch64.zig+4
......@@ -121,6 +121,10 @@ pub fn clone() callconv(.Naked) usize {
121121 \\ beqz $a0, 1f # whether child process
122122 \\ jirl $zero, $ra, 0 # parent process return
123123 \\1:
124 \\ .cfi_undefined 1
125 \\ move $fp, $zero
126 \\ move $ra, $zero
127 \\
124128 \\ ld.d $t8, $sp, 0 # function pointer
125129 \\ ld.d $a0, $sp, 8 # argument pointer
126130 \\ 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 {
231231 \\ jr $ra
232232 \\ nop
233233 \\1:
234 \\ .cfi_undefined $ra
235 \\ move $fp, $zero
236 \\ move $ra, $zero
237 \\
234238 \\ lw $25, 0($sp)
235239 \\ lw $4, 4($sp)
236240 \\ jalr $25
lib/std/os/linux/mips64.zig+4
......@@ -210,6 +210,10 @@ pub fn clone() callconv(.Naked) usize {
210210 \\ jr $ra
211211 \\ nop
212212 \\1:
213 \\ .cfi_undefined $ra
214 \\ move $fp, $zero
215 \\ move $ra, $zero
216 \\
213217 \\ ld $25, 0($sp)
214218 \\ ld $4, 8($sp)
215219 \\ jalr $25
lib/std/os/linux/powerpc.zig+20-20
......@@ -133,14 +133,14 @@ pub fn clone() callconv(.Naked) usize {
133133 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
134134 // 0 3, 4, 5, 6, 7
135135 asm volatile (
136 \\ # store non-volatile regs r30, r31 on stack in order to put our
136 \\ # store non-volatile regs r29, r30 on stack in order to put our
137137 \\ # start func and its arg there
138 \\ stwu 30, -16(1)
139 \\ stw 31, 4(1)
138 \\ stwu 29, -16(1)
139 \\ stw 30, 4(1)
140140 \\
141 \\ # save r3 (func) into r30, and r6(arg) into r31
142 \\ mr 30, 3
143 \\ mr 31, 6
141 \\ # save r3 (func) into r29, and r6(arg) into r30
142 \\ mr 29, 3
143 \\ mr 30, 6
144144 \\
145145 \\ # create initial stack frame for new thread
146146 \\ clrrwi 4, 4, 4
......@@ -167,28 +167,28 @@ pub fn clone() callconv(.Naked) usize {
167167 \\ # compare sc result with 0
168168 \\ cmpwi cr7, 3, 0
169169 \\
170 \\ # if not 0, jump to end
171 \\ bne cr7, 2f
170 \\ # if not 0, restore stack and return
171 \\ beq cr7, 2f
172 \\ lwz 29, 0(1)
173 \\ lwz 30, 4(1)
174 \\ addi 1, 1, 16
175 \\ blr
172176 \\
173177 \\ #else: we're the child
178 \\ 2:
179 \\ .cfi_undefined lr
180 \\ li 31, 0
181 \\ mtlr 0
182 \\
174183 \\ #call funcptr: move arg (d) into r3
175 \\ mr 3, 31
176 \\ #move r30 (funcptr) into CTR reg
177 \\ mtctr 30
184 \\ mr 3, 30
185 \\ #move r29 (funcptr) into CTR reg
186 \\ mtctr 29
178187 \\ # call CTR reg
179188 \\ bctrl
180189 \\ # mov SYS_exit into r0 (the exit param is already in r3)
181190 \\ li 0, 1
182191 \\ 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
192192 );
193193}
194194
lib/std/os/linux/powerpc64.zig+6-1
......@@ -160,7 +160,12 @@ pub fn clone() callconv(.Naked) usize {
160160 \\ cmpwi cr7, 3, 0
161161 \\ bnelr cr7
162162 \\
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)
164169 \\ ld 3, 16(1)
165170 \\ ld 12, 8(1)
166171 \\ mtctr 12
lib/std/os/linux/riscv32.zig+5-1
......@@ -120,7 +120,11 @@ pub fn clone() callconv(.Naked) usize {
120120 \\ ret
121121 \\
122122 \\ # 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)
124128 \\ lw a0, 4(sp)
125129 \\ jalr a1
126130 \\
lib/std/os/linux/riscv64.zig+5-1
......@@ -120,7 +120,11 @@ pub fn clone() callconv(.Naked) usize {
120120 \\ ret
121121 \\
122122 \\ # 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)
124128 \\ ld a0, 8(sp)
125129 \\ jalr a1
126130 \\
lib/std/os/linux/s390x.zig+6-1
......@@ -133,7 +133,12 @@ pub fn clone() callconv(.Naked) usize {
133133 \\ltgr %%r2, %%r2
134134 \\bnzr %%r14
135135 \\
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)
137142 \\lg %%r1, 8(%%r15)
138143 \\lg %%r2, 16(%%r15)
139144 \\basr %%r14, %%r1
lib/std/os/linux/sparc64.zig+13-8
......@@ -198,29 +198,34 @@ pub fn clone() callconv(.Naked) usize {
198198 \\ mov %%i5, %%o3
199199 \\ ldx [%%fp + 0x8af], %%o4
200200 \\ t 0x6d
201 \\ bcs,pn %%xcc, 2f
201 \\ bcs,pn %%xcc, 1f
202202 \\ nop
203203 \\ # The child pid is returned in o0 while o1 tells if this
204204 \\ # process is # the child (=1) or the parent (=0).
205 \\ brnz %%o1, 1f
205 \\ brnz %%o1, 2f
206206 \\ nop
207207 \\ # Parent process, return the child pid
208208 \\ mov %%o0, %%i0
209209 \\ ret
210210 \\ restore
211211 \\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)
213223 \\ mov %%g0, %%fp
214224 \\ call %%g2
215225 \\ mov %%g3, %%o0
216226 \\ # Exit
217227 \\ mov 1, %%g1 // SYS_exit
218228 \\ t 0x6d
219 \\2:
220 \\ # The syscall failed
221 \\ sub %%g0, %%o0, %%i0
222 \\ ret
223 \\ restore
224229 );
225230}
226231
lib/std/os/linux/x86.zig+11-8
......@@ -148,19 +148,22 @@ pub fn clone() callconv(.Naked) usize {
148148 \\ movl $120,%%eax // SYS_clone
149149 \\ int $128
150150 \\ testl %%eax,%%eax
151 \\ jnz 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:
151 \\ jz 1f
159152 \\ popl %%edi
160153 \\ popl %%esi
161154 \\ popl %%ebx
162155 \\ popl %%ebp
163156 \\ 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
164167 );
165168}
166169
lib/std/os/linux/x86_64.zig+2
......@@ -116,8 +116,10 @@ pub fn clone() callconv(.Naked) usize {
116116 \\ testq %%rax,%%rax
117117 \\ jz 1f
118118 \\ retq
119 \\
119120 \\1: .cfi_undefined %%rip
120121 \\ xorl %%ebp,%%ebp
122 \\
121123 \\ popq %%rdi
122124 \\ callq *%%r9
123125 \\ movl %%eax,%%edi
lib/std/start.zig+45-6
......@@ -230,6 +230,29 @@ fn _start() callconv(.naked) noreturn {
230230 );
231231 }
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
233256 // Move this to the riscv prong below when this is resolved: https://github.com/ziglang/zig/issues/20918
234257 if (builtin.cpu.arch.isRISCV() and builtin.zig_backend != .stage2_riscv64) asm volatile (
235258 \\ .weak __global_pointer$
......@@ -247,7 +270,6 @@ fn _start() callconv(.naked) noreturn {
247270 // linker explicitly.
248271 asm volatile (switch (native_arch) {
249272 .x86_64 =>
250 \\ .cfi_undefined %%rip
251273 \\ xorl %%ebp, %%ebp
252274 \\ movq %%rsp, %%rdi
253275 \\ andq $-16, %%rsp
......@@ -279,8 +301,10 @@ fn _start() callconv(.naked) noreturn {
279301 ,
280302 .arm, .armeb, .thumb, .thumbeb =>
281303 // Note that this code must work for Thumb-1.
304 // r7 = FP (local), r11 = FP (unwind)
282305 \\ movs v1, #0
283 \\ mov fp, v1
306 \\ mov r7, v1
307 \\ mov r11, v1
284308 \\ mov lr, v1
285309 \\ mov a1, sp
286310 \\ subs v1, #16
......@@ -290,20 +314,23 @@ fn _start() callconv(.naked) noreturn {
290314 ,
291315 .csky =>
292316 // 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`
294 // to locate `_DYNAMIC` as well.
317 // position-independent code to work. We depend on this in `std.os.linux.pie` to locate
318 // `_DYNAMIC` as well.
319 // r8 = FP
295320 \\ grs t0, 1f
296321 \\ 1:
297322 \\ lrw gb, 1b@GOTPC
298323 \\ addu gb, t0
324 \\ movi r8, 0
299325 \\ movi lr, 0
300326 \\ mov a0, sp
301327 \\ andi sp, sp, -8
302328 \\ jmpi %[posixCallMainAndExit]
303329 ,
304330 .hexagon =>
305 // r29 = SP, r30 = FP
331 // r29 = SP, r30 = FP, r31 = LR
306332 \\ r30 = #0
333 \\ r31 = #0
307334 \\ r0 = r29
308335 \\ r29 = and(r29, #-16)
309336 \\ memw(r29 + #-8) = r29
......@@ -312,12 +339,13 @@ fn _start() callconv(.naked) noreturn {
312339 ,
313340 .loongarch32, .loongarch64 =>
314341 \\ move $fp, $zero
342 \\ move $ra, $zero
315343 \\ move $a0, $sp
316344 \\ bstrins.d $sp, $zero, 3, 0
317345 \\ b %[posixCallMainAndExit]
318346 ,
319347 .riscv32, .riscv64 =>
320 \\ li s0, 0
348 \\ li fp, 0
321349 \\ li ra, 0
322350 \\ mv a0, sp
323351 \\ andi sp, sp, -16
......@@ -371,28 +399,35 @@ fn _start() callconv(.naked) noreturn {
371399 ,
372400 .powerpc, .powerpcle =>
373401 // Set up the initial stack frame, and clear the back chain pointer.
402 // r1 = SP, r31 = FP
374403 \\ mr 3, 1
375404 \\ clrrwi 1, 1, 4
376405 \\ li 0, 0
377406 \\ stwu 1, -16(1)
378407 \\ stw 0, 0(1)
408 \\ li 31, 0
379409 \\ mtlr 0
380410 \\ b %[posixCallMainAndExit]
381411 ,
382412 .powerpc64, .powerpc64le =>
383413 // Set up the ToC and initial stack frame, and clear the back chain pointer.
414 // r1 = SP, r2 = ToC, r31 = FP
384415 \\ addis 2, 12, .TOC. - %[_start]@ha
385416 \\ addi 2, 2, .TOC. - %[_start]@l
386417 \\ mr 3, 1
387418 \\ clrrdi 1, 1, 4
388419 \\ li 0, 0
389420 \\ stdu 0, -32(1)
421 \\ li 31, 0
390422 \\ mtlr 0
391423 \\ b %[posixCallMainAndExit]
392424 \\ nop
393425 ,
394426 .s390x =>
395427 // 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
396431 \\ lgr %%r2, %%r15
397432 \\ lghi %%r0, -16
398433 \\ ngr %%r15, %%r0
......@@ -403,7 +438,9 @@ fn _start() callconv(.naked) noreturn {
403438 ,
404439 .sparc =>
405440 // argc is stored after a register window (16 registers * 4 bytes).
441 // i7 = LR
406442 \\ mov %%g0, %%fp
443 \\ mov %%g0, %%i7
407444 \\ add %%sp, 64, %%o0
408445 \\ and %%sp, -8, %%sp
409446 \\ ba,a %[posixCallMainAndExit]
......@@ -411,7 +448,9 @@ fn _start() callconv(.naked) noreturn {
411448 .sparc64 =>
412449 // argc is stored after a register window (16 registers * 8 bytes) plus the stack bias
413450 // (2047 bytes).
451 // i7 = LR
414452 \\ mov %%g0, %%fp
453 \\ mov %%g0, %%i7
415454 \\ add %%sp, 2175, %%o0
416455 \\ add %%sp, 2047, %%sp
417456 \\ and %%sp, -16, %%sp
src/Builtin.zig+3
......@@ -2,6 +2,7 @@ target: std.Target,
22zig_backend: std.builtin.CompilerBackend,
33output_mode: std.builtin.OutputMode,
44link_mode: std.builtin.LinkMode,
5unwind_tables: std.builtin.UnwindTables,
56is_test: bool,
67single_threaded: bool,
78link_libc: bool,
......@@ -40,6 +41,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
4041 \\
4142 \\pub const output_mode: std.builtin.OutputMode = .{p_};
4243 \\pub const link_mode: std.builtin.LinkMode = .{p_};
44 \\pub const unwind_tables: std.builtin.UnwindTables = .{p_};
4345 \\pub const is_test = {};
4446 \\pub const single_threaded = {};
4547 \\pub const abi: std.Target.Abi = .{p_};
......@@ -53,6 +55,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
5355 std.zig.fmtId(@tagName(zig_backend)),
5456 std.zig.fmtId(@tagName(opts.output_mode)),
5557 std.zig.fmtId(@tagName(opts.link_mode)),
58 std.zig.fmtId(@tagName(opts.unwind_tables)),
5659 opts.is_test,
5760 opts.single_threaded,
5861 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
12611261 // The "any" values provided by resolved config only account for
12621262 // explicitly-provided settings. We now make them additionally account
12631263 // 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 };
12651268 const any_non_single_threaded = options.config.any_non_single_threaded or !options.root_mod.single_threaded;
12661269 const any_sanitize_thread = options.config.any_sanitize_thread or options.root_mod.sanitize_thread;
12671270 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;
12701273 const build_id = options.build_id orelse .none;
12711274
12721275 const link_libc = options.config.link_libc;
......@@ -1354,6 +1357,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
13541357 cache.hash.add(options.config.pie);
13551358 cache.hash.add(options.config.lto);
13561359 cache.hash.add(options.config.link_mode);
1360 cache.hash.add(options.config.any_unwind_tables);
13571361 cache.hash.add(options.function_sections);
13581362 cache.hash.add(options.data_sections);
13591363 cache.hash.add(link_libc);
......@@ -5553,10 +5557,17 @@ pub fn addCCArgs(
55535557 try argv.append("-Werror=date-time");
55545558 }
55555559
5556 if (mod.unwind_tables) {
5557 try argv.append("-funwind-tables");
5558 } else {
5559 try argv.append("-fno-unwind-tables");
5560 switch (mod.unwind_tables) {
5561 .none => {
5562 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"),
55605571 }
55615572 },
55625573 .shared_library, .ll, .bc, .unknown, .static_library, .object, .def, .zig, .res, .manifest => {},
......@@ -6288,6 +6299,7 @@ pub const CrtFileOptions = struct {
62886299 function_sections: ?bool = null,
62896300 data_sections: ?bool = null,
62906301 omit_frame_pointer: ?bool = null,
6302 unwind_tables: ?std.builtin.UnwindTables = null,
62916303 pic: ?bool = null,
62926304 no_builtin: ?bool = null,
62936305};
......@@ -6349,7 +6361,8 @@ pub fn build_crt_file(
63496361 // Some libcs (e.g. musl) are opinionated about -fomit-frame-pointer.
63506362 .omit_frame_pointer = options.omit_frame_pointer orelse comp.root_mod.omit_frame_pointer,
63516363 .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,
63536366 // Some CRT objects (e.g. musl's rcrt1.o and Scrt1.o) are opinionated about PIC.
63546367 .pic = options.pic orelse comp.root_mod.pic,
63556368 .optimize_mode = comp.compilerRtOptMode(),
src/Compilation/Config.zig+14-10
......@@ -12,13 +12,14 @@ link_libunwind: bool,
1212/// True if and only if the c_source_files field will have nonzero length when
1313/// calling Compilation.create.
1414any_c_source_files: bool,
15/// This is true if any Module has unwind_tables set explicitly to true. Until
16/// Compilation.create is called, it is possible for this to be false while in
17/// fact all Module instances have unwind_tables=true due to the default
18/// being unwind_tables=true. After Compilation.create is called this will
19/// also take into account the default setting, making this value true if and
20/// only if any Module has unwind_tables set to true.
21any_unwind_tables: bool,
15/// This is not `.none` if any `Module` has `unwind_tables` set explicitly to a
16/// value other than `.none`. Until `Compilation.create()` is called, it is
17/// possible for this to be `.none` while in fact all `Module` instances have
18/// `unwind_tables != .none` due to the default. After `Compilation.create()` is
19/// called, this will also take into account the default setting, making this
20/// value `.sync` or `.@"async"` if and only if any `Module` has
21/// `unwind_tables != .none`.
22any_unwind_tables: std.builtin.UnwindTables,
2223/// This is true if any Module has single_threaded set explicitly to false. Until
2324/// Compilation.create is called, it is possible for this to be false while in
2425/// fact all Module instances have single_threaded=false due to the default
......@@ -85,7 +86,7 @@ pub const Options = struct {
8586 any_non_single_threaded: bool = false,
8687 any_sanitize_thread: bool = false,
8788 any_fuzz: bool = false,
88 any_unwind_tables: bool = false,
89 any_unwind_tables: std.builtin.UnwindTables = .none,
8990 any_dyn_libs: bool = false,
9091 any_c_source_files: bool = false,
9192 any_non_stripped: bool = false,
......@@ -356,8 +357,11 @@ pub fn resolve(options: Options) ResolveError!Config {
356357 break :b false;
357358 };
358359
359 const any_unwind_tables = options.any_unwind_tables or
360 link_libunwind or target_util.needUnwindTables(target);
360 const any_unwind_tables = b: {
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
362366 const link_mode = b: {
363367 const explicitly_exe_or_dyn_lib = switch (options.output_mode) {
src/Package/Module.zig+4-3
......@@ -27,7 +27,7 @@ red_zone: bool,
2727sanitize_c: bool,
2828sanitize_thread: bool,
2929fuzz: bool,
30unwind_tables: bool,
30unwind_tables: std.builtin.UnwindTables,
3131cc_argv: []const []const u8,
3232/// (SPIR-V) whether to generate a structured control flow graph or not
3333structured_cfg: bool,
......@@ -91,7 +91,7 @@ pub const CreateOptions = struct {
9191 /// other number means stack protection with that buffer size.
9292 stack_protector: ?u32 = null,
9393 red_zone: ?bool = null,
94 unwind_tables: ?bool = null,
94 unwind_tables: ?std.builtin.UnwindTables = null,
9595 sanitize_c: ?bool = null,
9696 sanitize_thread: ?bool = null,
9797 fuzz: ?bool = null,
......@@ -112,7 +112,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
112112 if (options.inherited.sanitize_thread == true) assert(options.global.any_sanitize_thread);
113113 if (options.inherited.fuzz == true) assert(options.global.any_fuzz);
114114 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);
116116 if (options.inherited.error_tracing == true) assert(options.global.any_error_tracing);
117117
118118 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 {
382382 .zig_backend = zig_backend,
383383 .output_mode = options.global.output_mode,
384384 .link_mode = options.global.link_mode,
385 .unwind_tables = options.global.any_unwind_tables,
385386 .is_test = options.global.is_test,
386387 .single_threaded = single_threaded,
387388 .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
84428442}
84438443
84448444fn 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
84458449 return std.meta.stringToEnum(Register, name);
84468450}
84478451
src/clang_options_data.zig+16-2
......@@ -2757,7 +2757,14 @@ flagpd1("fast"),
27572757flagpd1("fastcp"),
27582758flagpd1("fastf"),
27592759flagpd1("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},
27612768flagpd1("fauto-import"),
27622769flagpd1("fauto-profile"),
27632770flagpd1("fauto-profile-accurate"),
......@@ -3247,7 +3254,14 @@ flagpd1("fno-assume-sane-operator-new"),
32473254flagpd1("fno-assume-unique-vtables"),
32483255flagpd1("fno-assumptions"),
32493256flagpd1("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},
32513265flagpd1("fno-auto-import"),
32523266flagpd1("fno-auto-profile"),
32533267flagpd1("fno-auto-profile-accurate"),
src/codegen/llvm.zig+5-2
......@@ -3141,8 +3141,11 @@ pub const Object = struct {
31413141 } }, &o.builder);
31423142 }
31433143 try attributes.addFnAttr(.nounwind, &o.builder);
3144 if (owner_mod.unwind_tables) {
3145 try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder);
3144 if (owner_mod.unwind_tables != .none) {
3145 try attributes.addFnAttr(
3146 .{ .uwtable = if (owner_mod.unwind_tables == .@"async") .@"async" else .sync },
3147 &o.builder,
3148 );
31463149 }
31473150 if (owner_mod.no_builtin) {
31483151 // 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
397397
398398 const optimize_mode = comp.compilerRtOptMode();
399399 const strip = comp.compilerRtStrip();
400 const unwind_tables = true;
401400
402401 const config = Compilation.Config.resolve(.{
403402 .output_mode = output_mode,
......@@ -409,7 +408,6 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
409408 .root_optimize_mode = optimize_mode,
410409 .root_strip = strip,
411410 .link_libc = true,
412 .any_unwind_tables = unwind_tables,
413411 .lto = comp.config.lto,
414412 .any_sanitize_thread = comp.config.any_sanitize_thread,
415413 }) catch |err| {
......@@ -440,7 +438,12 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
440438 .valgrind = false,
441439 .optimize_mode = optimize_mode,
442440 .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",
444447 .pic = comp.root_mod.pic,
445448 },
446449 .global = config,
src/libunwind.zig+2-1
......@@ -65,7 +65,8 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
6565 .sanitize_c = false,
6666 .sanitize_thread = false,
6767 // 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",
6970 .pic = if (target_util.supports_fpic(target)) true else null,
7071 .optimize_mode = comp.compilerRtOptMode(),
7172 },
src/main.zig+46-8
......@@ -510,6 +510,7 @@ const usage_build_generic =
510510 \\ -ffuzz Enable fuzz testing instrumentation
511511 \\ -fno-fuzz Disable fuzz testing instrumentation
512512 \\ -funwind-tables Always produce unwind table entries for all functions
513 \\ -fasync-unwind-tables Always produce asynchronous unwind table entries for all functions
513514 \\ -fno-unwind-tables Never produce unwind table entries
514515 \\ -ferror-tracing Enable error tracing in ReleaseFast mode
515516 \\ -fno-error-tracing Disable error tracing in Debug and ReleaseSafe mode
......@@ -1385,9 +1386,11 @@ fn buildOutputType(
13851386 } else if (mem.eql(u8, arg, "-fno-lto")) {
13861387 create_module.opts.lto = false;
13871388 } 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";
13891392 } else if (mem.eql(u8, arg, "-fno-unwind-tables")) {
1390 mod_opts.unwind_tables = false;
1393 mod_opts.unwind_tables = .none;
13911394 } else if (mem.eql(u8, arg, "-fstack-check")) {
13921395 mod_opts.stack_check = true;
13931396 } else if (mem.eql(u8, arg, "-fno-stack-check")) {
......@@ -1973,8 +1976,27 @@ fn buildOutputType(
19731976 }
19741977 },
19751978 .no_stack_protector => mod_opts.stack_protector = 0,
1976 .unwind_tables => mod_opts.unwind_tables = true,
1977 .no_unwind_tables => mod_opts.unwind_tables = false,
1979 // The way these unwind table options are processed in GCC and Clang is crazy
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 },
19782000 .nostdlib => {
19792001 create_module.opts.ensure_libc_on_non_freestanding = false;
19802002 create_module.opts.ensure_libcpp_on_non_freestanding = false;
......@@ -2788,8 +2810,15 @@ fn buildOutputType(
27882810 create_module.opts.any_sanitize_thread = true;
27892811 if (mod_opts.fuzz == true)
27902812 create_module.opts.any_fuzz = true;
2791 if (mod_opts.unwind_tables == true)
2792 create_module.opts.any_unwind_tables = true;
2813 if (mod_opts.unwind_tables) |uwt| switch (uwt) {
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 };
27932822 if (mod_opts.strip == false)
27942823 create_module.opts.any_non_stripped = true;
27952824 if (mod_opts.error_tracing == true)
......@@ -5713,6 +5742,8 @@ pub const ClangArgIterator = struct {
57135742 no_lto,
57145743 unwind_tables,
57155744 no_unwind_tables,
5745 asynchronous_unwind_tables,
5746 no_asynchronous_unwind_tables,
57165747 nostdlib,
57175748 nostdlib_cpp,
57185749 shared,
......@@ -7435,8 +7466,15 @@ fn handleModArg(
74357466 create_module.opts.any_sanitize_thread = true;
74367467 if (mod_opts.fuzz == true)
74377468 create_module.opts.any_fuzz = true;
7438 if (mod_opts.unwind_tables == true)
7439 create_module.opts.any_unwind_tables = true;
7469 if (mod_opts.unwind_tables) |uwt| switch (uwt) {
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 };
74407478 if (mod_opts.strip == false)
74417479 create_module.opts.any_non_stripped = true;
74427480 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
2424 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
2525 defer arena_allocator.deinit();
2626 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
2832 switch (crt_file) {
2933 .crt2_o => {
......@@ -41,7 +45,9 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
4145 .owner = undefined,
4246 },
4347 };
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 });
4551 },
4652
4753 .dllcrt2_o => {
......@@ -56,7 +62,9 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
5662 .owner = undefined,
5763 },
5864 };
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 });
6068 },
6169
6270 .mingw32_lib => {
......@@ -73,7 +81,6 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
7381 .owner = undefined,
7482 });
7583 }
76 const target = comp.getTarget();
7784 if (target.cpu.arch == .x86 or target.cpu.arch == .x86_64) {
7885 for (mingw32_x86_src) |dep| {
7986 try c_source_files.append(.{
......@@ -118,7 +125,9 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
118125 } else {
119126 @panic("unsupported arch");
120127 }
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 });
122131 },
123132 }
124133}
src/target.zig+11-2
......@@ -4,6 +4,7 @@ const assert = std.debug.assert;
44const Type = @import("Type.zig");
55const AddressSpace = std.builtin.AddressSpace;
66const Alignment = @import("InternPool.zig").Alignment;
7const Compilation = @import("Compilation.zig");
78const Feature = @import("Zcu.zig").Feature;
89
910pub const default_stack_protector_buffer_size = 4;
......@@ -408,8 +409,16 @@ pub fn clangSupportsNoImplicitFloatArg(target: std.Target) bool {
408409 };
409410}
410411
411pub fn needUnwindTables(target: std.Target) bool {
412 return target.os.tag == .windows or target.isDarwin() or std.debug.Dwarf.abi.supportsUnwinding(target);
412pub fn needUnwindTables(target: std.Target, libunwind: bool, libtsan: bool) std.builtin.UnwindTables {
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;
413422}
414423
415424pub fn defaultAddressSpace(
test/standalone/stack_iterator/build.zig+3-3
......@@ -23,7 +23,7 @@ pub fn build(b: *std.Build) void {
2323 .root_source_file = b.path("unwind.zig"),
2424 .target = target,
2525 .optimize = optimize,
26 .unwind_tables = if (target.result.isDarwin()) true else null,
26 .unwind_tables = if (target.result.isDarwin()) .@"async" else null,
2727 .omit_frame_pointer = false,
2828 });
2929
......@@ -46,7 +46,7 @@ pub fn build(b: *std.Build) void {
4646 .root_source_file = b.path("unwind.zig"),
4747 .target = target,
4848 .optimize = optimize,
49 .unwind_tables = true,
49 .unwind_tables = .@"async",
5050 .omit_frame_pointer = true,
5151 });
5252
......@@ -85,7 +85,7 @@ pub fn build(b: *std.Build) void {
8585 .root_source_file = b.path("shared_lib_unwind.zig"),
8686 .target = target,
8787 .optimize = optimize,
88 .unwind_tables = if (target.result.isDarwin()) true else null,
88 .unwind_tables = if (target.result.isDarwin()) .@"async" else null,
8989 .omit_frame_pointer = true,
9090 });
9191
tools/update_clang_options.zig+8
......@@ -110,6 +110,14 @@ const known_options = [_]KnownOpt{
110110 .name = "fno-unwind-tables",
111111 .ident = "no_unwind_tables",
112112 },
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 },
113121 .{
114122 .name = "nolibc",
115123 .ident = "nostdlib",