1#	$NetBSD: asan_common.subr,v 1.3 2022/06/12 08:55:36 skrll Exp $
2#
3# Copyright (c) 2018, 2019 The NetBSD Foundation, Inc.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25# POSSIBILITY OF SUCH DAMAGE.
26#
27
28SUPPORT='n'
29test_target() {
30	if uname -p | grep -q "aarch64"; then
31		SUPPORT='y'
32	fi
33
34	if uname -m | grep -q "amd64"; then
35		SUPPORT='y'
36	fi
37
38	if uname -m | grep -q "i386"; then
39		SUPPORT='y'
40	fi
41}
42
43atf_test_case target_not_supported
44target_not_supported_head()
45{
46	atf_set "descr" "Test forced skip"
47}
48
49target_not_supported_body()
50{
51	atf_skip "Target is not supported"
52}
53
54# Add a new test case, with head & body.
55# asan_test_case <test-name> <description> <check-output>
56asan_test_case() {
57	atf_test_case "$1"
58	eval "$1_head() {
59		atf_set 'descr' 'compile and run \"$2\"'
60		atf_set 'require.progs' 'cc paxctl'
61	}"
62
63	atf_test_case "$1_profile"
64	eval "$1_head() {
65		atf_set 'descr' 'compile and run \"$2\" with profiling option'
66		atf_set 'require.progs' 'cc paxctl'
67	}"
68
69	atf_test_case "$1_pic"
70	eval "$1_head() {
71		atf_set 'descr' 'compile and run PIC \"$2\"'
72		atf_set 'require.progs' 'cc paxctl'
73	}"
74
75	atf_test_case "$1_pie"
76	eval "$1_head() {
77		atf_set 'descr' 'compile and run position independent (PIE) \"$2\"'
78		atf_set 'require.progs' 'cc paxctl'
79	}"
80
81	atf_test_case "${1}32"
82	eval "$1_head() {
83		atf_set 'descr' 'compile and run \"$2\" for/in netbsd32 emulation'
84		atf_set 'require.progs' 'cc paxctl file diff cat'
85	}"
86
87	eval "$1_body() {
88		echo \"\$ASAN_CODE\" > test.c
89		cc -fsanitize=address -o test test.c
90		paxctl +a test
91		atf_check -s not-exit:0 -o not-match:'CHECK\n' -e match:'$3' ./test
92	}
93
94	$1_profile_body() {
95		echo \"\$ASAN_CODE\" > test.c
96		cc -fsanitize=address -static -o test -pg test.c
97		paxctl +a test
98		atf_check -s not-exit:0 -o not-match:'CHECK\n' -e match:'$3' ./test
99	}
100
101	$1_pic_body() {
102		echo \"\$ASAN_CODE\" > test.c
103		cc -DPIC_FOO -fsanitize=address -fPIC -shared -o libtest.so test.c
104		cc -DPIC_MAIN -o test test.c -fsanitize=address -L. -ltest
105		paxctl +a test
106
107		export LD_LIBRARY_PATH=.
108		atf_check -s not-exit:0 -o not-match:'CHECK\n' -e match:'$3' ./test
109	}
110
111	$1_pie_body() {
112		# check whether this arch supports -pice
113		if ! cc -pie -dM -E - < /dev/null 2>/dev/null >/dev/null; then
114			atf_set_skip 'cc -pie not supported on this architecture'
115		fi
116		echo \"\$ASAN_CODE\" > test.c
117		cc -fsanitize=address -o test -fpie -pie test.c
118		paxctl +a test
119		atf_check -s not-exit:0 -o not-match:'CHECK\n' -e match:'$3' ./test
120	}
121
122	${1}32_body() {
123		# check whether this arch is 64bit
124		if ! cc -dM -E - < /dev/null | fgrep -q _LP64; then
125			atf_skip 'this is not a 64 bit architecture'
126		fi
127		if ! cc -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then
128			atf_skip 'cc -m32 not supported on this architecture'
129		else
130			if fgrep -q _LP64 ./def32; then
131				atf_fail 'cc -m32 does not generate netbsd32 binaries'
132			fi
133		fi
134
135		echo \"\$ASAN_CODE\" > test.c
136		cc -fsanitize=address -o df32 -m32 test.c
137		cc -fsanitize=address -o df64 test.c
138		file -b ./df32 > ./ftype32
139		file -b ./df64 > ./ftype64
140		if diff ./ftype32 ./ftype64 >/dev/null; then
141			atf_fail 'generated binaries do not differ'
142		fi
143		echo '32bit binaries on this platform are:'
144		cat ./ftype32
145		echo 'While native (64bit) binaries are:'
146		cat ./ftype64
147		paxctl +a df32
148		atf_check -s not-exit:0 -o not-match:'CHECK\n' -e match:'$3' ./df32
149
150# and another test with profile 32bit binaries
151		cc -fsanitize=address -static -o test -pg -m32 test.c
152		paxctl +a test
153		atf_check -s not-exit:0 -o not-match:'CHECK\n' -e match:'$3' ./test
154	}"
155}
156
157asan_add_test_cases() {
158	test_target
159	test $SUPPORT = 'n' && {
160		atf_add_test_case target_not_supported
161		return 0
162	}
163
164	atf_add_test_case "$1"
165#	atf_add_test_case "$1_profile"
166	atf_add_test_case "$1_pic"
167	atf_add_test_case "$1_pie"
168#	atf_add_test_case "${1}32"
169	# static option not supported
170	# -static and -fsanitize=address can't be used together for compilation
171	# (gcc version 5.4.0 and clang 7.1) tested on April 2nd 2018.
172}
173