1#	$NetBSD: t_static_destructor.sh,v 1.6 2022/06/12 15:08:38 skrll 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	cat > test.cpp << EOF
112#include <iostream>
113struct A {
114	int i;
115	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
116	~A() {std::cout << "DTOR A:" << i << std::endl;}
117};
118struct B {
119	A *m_a;
120	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
121	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
122};
123int main(void) {struct B b;return 0;}
124EOF
125	atf_check -s exit:0 -o ignore -e ignore c++ -static -pg -o hello test.cpp
126	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
127}
128
129static_destructor_profile_32_body() {
130	# check whether this arch is 64bit
131	if ! c++ -dM -E - < /dev/null | fgrep -q _LP64; then
132		atf_skip "this is not a 64 bit architecture"
133	fi
134	if ! c++ -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then
135		atf_skip "c++ -m32 not supported on this architecture"
136	else
137		if fgrep -q _LP64 ./def32; then
138			atf_fail "c++ -m32 does not generate netbsd32 binaries"
139		fi
140	fi
141
142	cat > test.cpp << EOF
143#include <iostream>
144struct A {
145	int i;
146	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
147	~A() {std::cout << "DTOR A:" << i << std::endl;}
148};
149struct B {
150	A *m_a;
151	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
152	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
153};
154int main(void) {struct B b;return 0;}
155EOF
156	atf_check -s exit:0 -o ignore -e ignore c++ -static -m32 -pg -o hello test.cpp
157	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
158}
159
160
161static_destructor_static_body() {
162	cat > test.cpp << EOF
163#include <iostream>
164struct A {
165	int i;
166	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
167	~A() {std::cout << "DTOR A:" << i << std::endl;}
168};
169struct B {
170	A *m_a;
171	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
172	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
173};
174int main(void) {struct B b;return 0;}
175EOF
176	atf_check -s exit:0 -o ignore -e ignore c++ -static -o hello test.cpp
177	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
178}
179
180static_destructor_pic_body() {
181	cat > test.cpp << EOF
182#include <cstdlib>
183int callpic(void);
184int main(void) {callpic();exit(0);}
185EOF
186	cat > pic.cpp << EOF
187#include <iostream>
188struct A {
189	int i;
190	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
191	~A() {std::cout << "DTOR A:" << i << std::endl;}
192};
193struct B {
194	A *m_a;
195	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
196	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
197};
198int callpic(void) {struct B b;}
199EOF
200
201	atf_check -s exit:0 -o ignore -e ignore \
202	    c++ -fPIC -shared -o libtest.so pic.cpp
203	atf_check -s exit:0 -o ignore -e ignore \
204	    c++ -o hello test.cpp -L. -ltest
205
206	export LD_LIBRARY_PATH=.
207	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
208}
209
210static_destructor_pic_32_body() {
211	# check whether this arch is 64bit
212	if ! c++ -dM -E - < /dev/null | fgrep -q _LP64; then
213		atf_skip "this is not a 64 bit architecture"
214	fi
215	if ! c++ -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then
216		atf_skip "c++ -m32 not supported on this architecture"
217	else
218		if fgrep -q _LP64 ./def32; then
219			atf_fail "c++ -m32 does not generate netbsd32 binaries"
220		fi
221	fi
222
223	cat > test.cpp << EOF
224#include <cstdlib>
225int callpic(void);
226int main(void) {callpic();exit(0);}
227EOF
228	cat > pic.cpp << EOF
229#include <iostream>
230struct A {
231	int i;
232	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
233	~A() {std::cout << "DTOR A:" << i << std::endl;}
234};
235struct B {
236	A *m_a;
237	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
238	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
239};
240int callpic(void) {struct B b;}
241EOF
242
243	atf_check -s exit:0 -o ignore -e ignore \
244	    c++ -m32 -fPIC -shared -o libtest.so pic.cpp
245	atf_check -s exit:0 -o ignore -e ignore \
246	    c++ -m32 -o hello test.cpp -L. -ltest
247
248	export LD_LIBRARY_PATH=.
249	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
250}
251
252static_destructor_pic_profile_body() {
253	cat > test.cpp << EOF
254#include <cstdlib>
255int callpic(void);
256int main(void) {callpic();exit(0);}
257EOF
258	cat > pic.cpp << EOF
259#include <iostream>
260struct A {
261	int i;
262	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
263	~A() {std::cout << "DTOR A:" << i << std::endl;}
264};
265struct B {
266	A *m_a;
267	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
268	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
269};
270int callpic(void) {struct B b;}
271EOF
272
273	atf_check -s exit:0 -o ignore -e ignore \
274	    c++ -pg -fPIC -shared -o libtest.so pic.cpp
275	atf_check -s exit:0 -o ignore -e ignore \
276	    c++ -pg -o hello test.cpp -L. -ltest
277
278	export LD_LIBRARY_PATH=.
279	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
280}
281
282static_destructor_pic_profile_32_body() {
283	# check whether this arch is 64bit
284	if ! c++ -dM -E - < /dev/null | fgrep -q _LP64; then
285		atf_skip "this is not a 64 bit architecture"
286	fi
287	if ! c++ -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then
288		atf_skip "c++ -m32 not supported on this architecture"
289	else
290		if fgrep -q _LP64 ./def32; then
291			atf_fail "c++ -m32 does not generate netbsd32 binaries"
292		fi
293	fi
294
295	cat > test.cpp << EOF
296#include <cstdlib>
297int callpic(void);
298int main(void) {callpic();exit(0);}
299EOF
300	cat > pic.cpp << EOF
301#include <iostream>
302struct A {
303	int i;
304	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
305	~A() {std::cout << "DTOR A:" << i << std::endl;}
306};
307struct B {
308	A *m_a;
309	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
310	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
311};
312int callpic(void) {struct B b;}
313EOF
314
315	atf_check -s exit:0 -o ignore -e ignore \
316	    c++ -m32 -pg -fPIC -shared -o libtest.so pic.cpp
317	atf_check -s exit:0 -o ignore -e ignore \
318	    c++ -m32 -pg -o hello test.cpp -L. -ltest
319
320	export LD_LIBRARY_PATH=.
321	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
322}
323
324static_destructor_pie_body() {
325	# check whether this arch supports -pie
326	if ! c++ -pie -dM -E - < /dev/null 2>/dev/null >/dev/null; then
327		atf_skip "c++ -pie not supported on this architecture"
328	fi
329	cat > test.cpp << EOF
330#include <iostream>
331struct A {
332	int i;
333	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
334	~A() {std::cout << "DTOR A:" << i << std::endl;}
335};
336struct B {
337	A *m_a;
338	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
339	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
340};
341int main(void) {struct B b;return 0;}
342EOF
343	atf_check -s exit:0 -o ignore -e ignore c++ -fpie -pie -o hello test.cpp
344	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
345}
346
347static_destructor32_body() {
348	# check whether this arch is 64bit
349	if ! c++ -dM -E - < /dev/null | fgrep -q _LP64; then
350		atf_skip "this is not a 64 bit architecture"
351	fi
352	if ! c++ -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then
353		atf_skip "c++ -m32 not supported on this architecture"
354	else
355		if fgrep -q _LP64 ./def32; then
356			atf_fail "c++ -m32 does not generate netbsd32 binaries"
357		fi
358	fi
359
360	cat > test.cpp << EOF
361#include <iostream>
362struct A {
363	int i;
364	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
365	~A() {std::cout << "DTOR A:" << i << std::endl;}
366};
367struct B {
368	A *m_a;
369	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
370	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
371};
372int main(void) {struct B b;return 0;}
373EOF
374	atf_check -s exit:0 -o ignore -e ignore c++ -o hello32 -m32 test.cpp
375	atf_check -s exit:0 -o ignore -e ignore c++ -o hello64 test.cpp
376	file -b ./hello32 > ./ftype32
377	file -b ./hello64 > ./ftype64
378	if diff ./ftype32 ./ftype64 >/dev/null; then
379		atf_fail "generated binaries do not differ"
380	fi
381	echo "32bit binaries on this platform are:"
382	cat ./ftype32
383	echo "While native (64bit) binaries are:"
384	cat ./ftype64
385	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello32
386
387	# do another test with static 32bit binaries
388	cat > test.cpp << EOF
389#include <iostream>
390struct A {
391	int i;
392	A(int i):i(i){std::cout << "CTOR A" << std::endl;}
393	~A() {std::cout << "DTOR A:" << i << std::endl;}
394};
395struct B {
396	A *m_a;
397	B(){static A s_a(10);m_a=&s_a;std::cout << "CTOR B" << std::endl;}
398	~B(){std::cout << "DTOR B:" << (*m_a).i << std::endl;(*m_a).i = 20;}
399};
400int main(void) {struct B b;return 0;}
401EOF
402	atf_check -s exit:0 -o ignore -e ignore c++ -o hello -m32 \
403	    -static test.cpp
404	atf_check -s exit:0 -o inline:"CTOR A\nCTOR B\nDTOR B:10\nDTOR A:20\n" ./hello
405}
406
407atf_init_test_cases()
408{
409
410	atf_add_test_case static_destructor
411	atf_add_test_case static_destructor_profile
412	atf_add_test_case static_destructor_pic
413	atf_add_test_case static_destructor_pie
414	atf_add_test_case static_destructor32
415	atf_add_test_case static_destructor_static
416	atf_add_test_case static_destructor_pic_32
417	atf_add_test_case static_destructor_pic_profile
418	atf_add_test_case static_destructor_pic_profile_32
419	atf_add_test_case static_destructor_profile_32
420}
421