t_static_destructor.sh revision 1.8
1#	$NetBSD: t_static_destructor.sh,v 1.8 2025/09/24 13:52:25 rin Exp $
2#
3# Copyright (c) 2017 The NetBSD Foundation, Inc.
4# All rights reserved.
5#
6# This code is derived from software contributed to The NetBSD Foundation
7# by Kamil Rytarowski.
8#
9# Redistribution and use in source and binary forms, with or without
10# modification, are permitted provided that the following conditions
11# are met:
12# 1. Redistributions of source code must retain the above copyright
13#    notice, this list of conditions and the following disclaimer.
14# 2. Redistributions in binary form must reproduce the above copyright
15#    notice, this list of conditions and the following disclaimer in the
16#    documentation and/or other materials provided with the distribution.
17#
18# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28# POSSIBILITY OF SUCH DAMAGE.
29#
30
31atf_test_case static_destructor
32static_destructor_head() {
33	atf_set "descr" "compile and run \"hello world\""
34	atf_set "require.progs" "c++"
35}
36
37atf_test_case static_destructor_profile
38static_destructor_profile_head() {
39	atf_set "descr" "compile and run \"hello world\" with profiling option"
40	atf_set "require.progs" "c++"
41}
42
43atf_test_case static_destructor_static
44static_destructor_static_head() {
45	atf_set "descr" "compile and run \"hello world\" with static option"
46	atf_set "require.progs" "c++"
47}
48
49atf_test_case static_destructor_pic
50static_destructor_pic_head() {
51	atf_set "descr" "compile and run PIC \"hello world\""
52	atf_set "require.progs" "c++"
53}
54
55atf_test_case static_destructor_pic_32
56static_destructor_pic_32_head() {
57	atf_set "descr" "compile and run 32-bit PIC \"hello world\""
58	atf_set "require.progs" "c++"
59}
60
61atf_test_case static_destructor_pic_profile
62static_destructor_pic_profile_head() {
63	atf_set "descr" "compile and run PIC \"hello world\" with profiling option"
64	atf_set "require.progs" "c++"
65}
66
67atf_test_case static_destructor_pic_profile_32
68static_destructor_pic_profile_32_head() {
69	atf_set "descr" "compile and run 32-bit PIC \"hello world\" with profiling option"
70	atf_set "require.progs" "c++"
71}
72
73atf_test_case static_destructor_profile_32
74static_destructor_profile_32_head() {
75	atf_set "descr" "compile and run 32-bit \"hello world\" with profiling option"
76	atf_set "require.progs" "c++"
77}
78
79atf_test_case static_destructor_pie
80static_destructor_pie_head() {
81	atf_set "descr" "compile and run position independent (PIE) \"hello world\""
82	atf_set "require.progs" "c++"
83}
84
85atf_test_case static_destructor32
86static_destructor32_head() {
87	atf_set "descr" "compile and run \"hello world\" for/in netbsd32 emulation"
88	atf_set "require.progs" "c++ file diff cat"
89}
90
91static_destructor_body() {
92	cat > test.cpp << EOF
93#include <iostream>
94struct A {
95	int i;
96	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
97	~A() {std::cout << "DTOR A:" << i << std::endl;}
98};
99struct B {
100	A *m_a;
101	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
102	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
103};
104int main(void) {struct B b;return 0;}
105EOF
106	atf_check -s exit:0 -o ignore -e ignore c++ -o hello test.cpp
107	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
108}
109
110static_destructor_profile_body() {
111	case `uname -m` in
112	riscv)	atf_expect_fail "PR port-riscv/59301:" \
113		    " riscv: missing MKPROFILE=yes support"
114		;;
115	esac
116
117	cat > test.cpp << EOF
118#include <iostream>
119struct A {
120	int i;
121	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
122	~A() {std::cout << "DTOR A:" << i << std::endl;}
123};
124struct B {
125	A *m_a;
126	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
127	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
128};
129int main(void) {struct B b;return 0;}
130EOF
131	atf_check -s exit:0 -o ignore -e ignore c++ -static -pg -o hello test.cpp
132	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
133}
134
135static_destructor_profile_32_body() {
136	# check whether this arch is 64bit
137	if ! c++ -dM -E - < /dev/null | fgrep -q _LP64; then
138		atf_skip "this is not a 64 bit architecture"
139	fi
140	if ! c++ -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then
141		atf_skip "c++ -m32 not supported on this architecture"
142	else
143		if fgrep -q _LP64 ./def32; then
144			atf_fail "c++ -m32 does not generate netbsd32 binaries"
145		fi
146	fi
147
148	case `uname -m` in
149	riscv)	atf_expect_fail "PR port-riscv/59301:" \
150		    " riscv: missing MKPROFILE=yes support"
151		;;
152	esac
153
154	cat > test.cpp << EOF
155#include <iostream>
156struct A {
157	int i;
158	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
159	~A() {std::cout << "DTOR A:" << i << std::endl;}
160};
161struct B {
162	A *m_a;
163	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
164	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
165};
166int main(void) {struct B b;return 0;}
167EOF
168	atf_check -s exit:0 -o ignore -e ignore c++ -static -m32 -pg -o hello test.cpp
169	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
170}
171
172
173static_destructor_static_body() {
174	cat > test.cpp << EOF
175#include <iostream>
176struct A {
177	int i;
178	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
179	~A() {std::cout << "DTOR A:" << i << std::endl;}
180};
181struct B {
182	A *m_a;
183	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
184	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
185};
186int main(void) {struct B b;return 0;}
187EOF
188	atf_check -s exit:0 -o ignore -e ignore c++ -static -o hello test.cpp
189	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
190}
191
192static_destructor_pic_body() {
193	cat > test.cpp << EOF
194#include <cstdlib>
195int callpic(void);
196int main(void) {callpic();exit(0);}
197EOF
198	cat > pic.cpp << EOF
199#include <iostream>
200struct A {
201	int i;
202	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
203	~A() {std::cout << "DTOR A:" << i << std::endl;}
204};
205struct B {
206	A *m_a;
207	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
208	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
209};
210int callpic(void) {struct B b;return 0;}
211EOF
212
213	atf_check -s exit:0 -o ignore -e ignore \
214	    c++ -fPIC -shared -o libtest.so pic.cpp
215	atf_check -s exit:0 -o ignore -e ignore \
216	    c++ -o hello test.cpp -L. -ltest
217
218	export LD_LIBRARY_PATH=.
219	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
220}
221
222static_destructor_pic_32_body() {
223	# check whether this arch is 64bit
224	if ! c++ -dM -E - < /dev/null | fgrep -q _LP64; then
225		atf_skip "this is not a 64 bit architecture"
226	fi
227	if ! c++ -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then
228		atf_skip "c++ -m32 not supported on this architecture"
229	else
230		if fgrep -q _LP64 ./def32; then
231			atf_fail "c++ -m32 does not generate netbsd32 binaries"
232		fi
233	fi
234
235	cat > test.cpp << EOF
236#include <cstdlib>
237int callpic(void);
238int main(void) {callpic();exit(0);}
239EOF
240	cat > pic.cpp << EOF
241#include <iostream>
242struct A {
243	int i;
244	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
245	~A() {std::cout << "DTOR A:" << i << std::endl;}
246};
247struct B {
248	A *m_a;
249	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
250	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
251};
252int callpic(void) {struct B b;return 0;}
253EOF
254
255	atf_check -s exit:0 -o ignore -e ignore \
256	    c++ -m32 -fPIC -shared -o libtest.so pic.cpp
257	atf_check -s exit:0 -o ignore -e ignore \
258	    c++ -m32 -o hello test.cpp -L. -ltest
259
260	export LD_LIBRARY_PATH=.
261	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
262}
263
264static_destructor_pic_profile_body() {
265	case `uname -m` in
266	riscv)	atf_expect_fail "PR port-riscv/59301:" \
267		    " riscv: missing MKPROFILE=yes support"
268		;;
269	esac
270
271	cat > test.cpp << EOF
272#include <cstdlib>
273int callpic(void);
274int main(void) {callpic();exit(0);}
275EOF
276	cat > pic.cpp << EOF
277#include <iostream>
278struct A {
279	int i;
280	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
281	~A() {std::cout << "DTOR A:" << i << std::endl;}
282};
283struct B {
284	A *m_a;
285	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
286	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
287};
288int callpic(void) {struct B b;return 0;}
289EOF
290
291	atf_check -s exit:0 -o ignore -e ignore \
292	    c++ -pg -fPIC -shared -o libtest.so pic.cpp
293	atf_check -s exit:0 -o ignore -e ignore \
294	    c++ -pg -o hello test.cpp -L. -ltest
295
296	export LD_LIBRARY_PATH=.
297	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
298}
299
300static_destructor_pic_profile_32_body() {
301	# check whether this arch is 64bit
302	if ! c++ -dM -E - < /dev/null | fgrep -q _LP64; then
303		atf_skip "this is not a 64 bit architecture"
304	fi
305	if ! c++ -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then
306		atf_skip "c++ -m32 not supported on this architecture"
307	else
308		if fgrep -q _LP64 ./def32; then
309			atf_fail "c++ -m32 does not generate netbsd32 binaries"
310		fi
311	fi
312
313	case `uname -m` in
314	riscv)	atf_expect_fail "PR port-riscv/59301:" \
315		    " riscv: missing MKPROFILE=yes support"
316		;;
317	esac
318
319	cat > test.cpp << EOF
320#include <cstdlib>
321int callpic(void);
322int main(void) {callpic();exit(0);}
323EOF
324	cat > pic.cpp << EOF
325#include <iostream>
326struct A {
327	int i;
328	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
329	~A() {std::cout << "DTOR A:" << i << std::endl;}
330};
331struct B {
332	A *m_a;
333	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
334	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
335};
336int callpic(void) {struct B b;return 0;}
337EOF
338
339	atf_check -s exit:0 -o ignore -e ignore \
340	    c++ -m32 -pg -fPIC -shared -o libtest.so pic.cpp
341	atf_check -s exit:0 -o ignore -e ignore \
342	    c++ -m32 -pg -o hello test.cpp -L. -ltest
343
344	export LD_LIBRARY_PATH=.
345	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
346}
347
348static_destructor_pie_body() {
349	# check whether this arch supports -pie
350	if ! c++ -pie -dM -E - < /dev/null 2>/dev/null >/dev/null; then
351		atf_skip "c++ -pie not supported on this architecture"
352	fi
353	cat > test.cpp << EOF
354#include <iostream>
355struct A {
356	int i;
357	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
358	~A() {std::cout << "DTOR A:" << i << std::endl;}
359};
360struct B {
361	A *m_a;
362	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
363	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
364};
365int main(void) {struct B b;return 0;}
366EOF
367	atf_check -s exit:0 -o ignore -e ignore c++ -fpie -pie -o hello test.cpp
368	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
369}
370
371static_destructor32_body() {
372	# check whether this arch is 64bit
373	if ! c++ -dM -E - < /dev/null | fgrep -q _LP64; then
374		atf_skip "this is not a 64 bit architecture"
375	fi
376	if ! c++ -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then
377		atf_skip "c++ -m32 not supported on this architecture"
378	else
379		if fgrep -q _LP64 ./def32; then
380			atf_fail "c++ -m32 does not generate netbsd32 binaries"
381		fi
382	fi
383
384	cat > test.cpp << EOF
385#include <iostream>
386struct A {
387	int i;
388	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
389	~A() {std::cout << "DTOR A:" << i << std::endl;}
390};
391struct B {
392	A *m_a;
393	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
394	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
395};
396int main(void) {struct B b;return 0;}
397EOF
398	atf_check -s exit:0 -o ignore -e ignore c++ -o hello32 -m32 test.cpp
399	atf_check -s exit:0 -o ignore -e ignore c++ -o hello64 test.cpp
400	file -b ./hello32 > ./ftype32
401	file -b ./hello64 > ./ftype64
402	if diff ./ftype32 ./ftype64 >/dev/null; then
403		atf_fail "generated binaries do not differ"
404	fi
405	echo "32bit binaries on this platform are:"
406	cat ./ftype32
407	echo "While native (64bit) binaries are:"
408	cat ./ftype64
409	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello32
410
411	# do another test with static 32bit binaries
412	cat > test.cpp << EOF
413#include <iostream>
414struct A {
415	int i;
416	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
417	~A() {std::cout << "DTOR A:" << i << std::endl;}
418};
419struct B {
420	A *m_a;
421	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
422	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
423};
424int main(void) {struct B b;return 0;}
425EOF
426	atf_check -s exit:0 -o ignore -e ignore c++ -o hello -m32 \
427	    -static test.cpp
428	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
429}
430
431atf_init_test_cases()
432{
433
434	atf_add_test_case static_destructor
435	atf_add_test_case static_destructor_profile
436	atf_add_test_case static_destructor_pic
437	atf_add_test_case static_destructor_pie
438	atf_add_test_case static_destructor32
439	atf_add_test_case static_destructor_static
440	atf_add_test_case static_destructor_pic_32
441	atf_add_test_case static_destructor_pic_profile
442	atf_add_test_case static_destructor_pic_profile_32
443	atf_add_test_case static_destructor_profile_32
444}
445