asan_common.subr revision 1.1
1#	$NetBSD: asan_common.subr,v 1.1 2019/01/29 19:56:37 mgorny 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 -m | grep -q "amd64"; then
31		SUPPORT='y'
32	fi
33
34	if uname -m | grep -q "i386"; then
35		SUPPORT='y'
36	fi
37}
38
39atf_test_case target_not_supported
40target_not_supported_head()
41{
42	atf_set "descr" "Test forced skip"
43}
44
45target_not_supported_body()
46{
47	atf_skip "Target is not supported"
48}
49
50# Add a new test case, with head & body.
51# asan_test_case <test-name> <description> <check-output>
52asan_test_case() {
53	atf_test_case "$1"
54	eval "$1_head() {
55		atf_set 'descr' 'compile and run \"$2\"'
56		atf_set 'require.progs' 'cc paxctl'
57	}"
58
59	atf_test_case "$1_profile"
60	eval "$1_head() {
61		atf_set 'descr' 'compile and run \"$2\" with profiling option'
62		atf_set 'require.progs' 'cc paxctl'
63	}"
64
65	atf_test_case "$1_pic"
66	eval "$1_head() {
67		atf_set 'descr' 'compile and run PIC \"$2\"'
68		atf_set 'require.progs' 'cc paxctl'
69	}"
70
71	atf_test_case "$1_pie"
72	eval "$1_head() {
73		atf_set 'descr' 'compile and run position independent (PIE) \"$2\"'
74		atf_set 'require.progs' 'cc paxctl'
75	}"
76
77	atf_test_case "${1}32"
78	eval "$1_head() {
79		atf_set 'descr' 'compile and run \"$2\" for/in netbsd32 emulation'
80		atf_set 'require.progs' 'cc paxctl file diff cat'
81	}"
82
83	eval "$1_body() {
84		echo \"\$ASAN_CODE\" > test.c
85		cc -fsanitize=address -o test test.c
86		paxctl +a test
87		atf_check -s not-exit:0 -o not-match:'CHECK\n' -e match:'$3' ./test
88	}
89
90	$1_profile_body() {
91		echo \"\$ASAN_CODE\" > test.c
92		cc -fsanitize=address -o test -pg test.c
93		paxctl +a test
94		atf_check -s not-exit:0 -o not-match:'CHECK\n' -e match:'$3' ./test
95	}
96
97	$1_pic_body() {
98		echo \"\$ASAN_CODE\" > test.c
99		cc -DPIC_FOO -fsanitize=address -fPIC -shared -o libtest.so test.c
100		cc -DPIC_MAIN -o test test.c -fsanitize=address -L. -ltest
101		paxctl +a test
102
103		export LD_LIBRARY_PATH=.
104		atf_check -s not-exit:0 -o not-match:'CHECK\n' -e match:'$3' ./test
105	}
106
107	$1_pie_body() {
108		# check whether this arch supports -pice
109		if ! cc -pie -dM -E - < /dev/null 2>/dev/null >/dev/null; then
110			atf_set_skip 'cc -pie not supported on this architecture'
111		fi
112		echo \"\$ASAN_CODE\" > test.c
113		cc -fsanitize=address -o test -fpie -pie test.c
114		paxctl +a test
115		atf_check -s not-exit:0 -o not-match:'CHECK\n' -e match:'$3' ./test
116	}
117
118	${1}32_body() {
119		# check whether this arch is 64bit
120		if ! cc -dM -E - < /dev/null | fgrep -q _LP64; then
121			atf_skip 'this is not a 64 bit architecture'
122		fi
123		if ! cc -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then
124			atf_skip 'cc -m32 not supported on this architecture'
125		else
126			if fgrep -q _LP64 ./def32; then
127				atf_fail 'cc -m32 does not generate netbsd32 binaries'
128			fi
129		fi
130
131		echo \"\$ASAN_CODE\" > test.c
132		cc -fsanitize=address -o df32 -m32 test.c
133		cc -fsanitize=address -o df64 test.c
134		file -b ./df32 > ./ftype32
135		file -b ./df64 > ./ftype64
136		if diff ./ftype32 ./ftype64 >/dev/null; then
137			atf_fail 'generated binaries do not differ'
138		fi
139		echo '32bit binaries on this platform are:'
140		cat ./ftype32
141		echo 'While native (64bit) binaries are:'
142		cat ./ftype64
143		paxctl +a df32
144		atf_check -s not-exit:0 -o not-match:'CHECK\n' -e match:'$3' ./df32
145
146# and another test with profile 32bit binaries
147		cc -fsanitize=address -o test -pg -m32 test.c
148		paxctl +a test
149		atf_check -s not-exit:0 -o not-match:'CHECK\n' -e match:'$3' ./test
150	}"
151}
152
153asan_add_test_cases() {
154	test_target
155	test $SUPPORT = 'n' && {
156		atf_add_test_case target_not_supported
157		return 0
158	}
159
160	atf_add_test_case "$1"
161#	atf_add_test_case "$1_profile"
162	atf_add_test_case "$1_pic"
163	atf_add_test_case "$1_pie"
164#	atf_add_test_case "${1}32"
165	# static option not supported
166	# -static and -fsanitize=address can't be used together for compilation
167	# (gcc version 5.4.0 and clang 7.1) tested on April 2nd 2018.
168}
169