1#	$NetBSD$
2#
3# Copyright (c) 2014 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
28################################################################################
29
30atf_test_case order_default
31order_default_head() {
32	atf_set "descr" "check if default object ordering works"
33	atf_set "require.progs" "cc" "ld" "readelf" "nm" "sed" "grep"
34}
35
36order_default_body() {
37	cat > test.x << EOF
38SECTIONS {
39	/* do nothing; but ld has implicit scripts internally */
40	/* which usually do: *(.data) *(.data.*) */
41}
42EOF
43	order_assert_descending
44}
45
46################################################################################
47
48atf_test_case order_merge
49order_merge_head() {
50	atf_set "descr" "check if glob merge keeps object ordering"
51	atf_set "require.progs" ${order_require_progs}
52}
53
54order_merge_body() {
55	cat > test.x << EOF
56SECTIONS {
57	.data : {
58		*(.data .data.*)
59	}
60}
61EOF
62	order_assert_descending
63}
64
65################################################################################
66
67atf_test_case order_reorder
68order_reorder_head() {
69	atf_set "descr" "check if object reordering works"
70	atf_set "require.progs" ${order_require_progs}
71}
72
73order_reorder_body() {
74	cat > test.x << EOF
75SECTIONS {
76	.data : {
77		*(.data)
78		*(.data.a)
79		*(.data.b)
80		*(.data.c)
81	}
82}
83EOF
84	order_assert_ascending
85}
86
87################################################################################
88
89atf_test_case order_sort
90order_sort_head() {
91	atf_set "descr" "check if object sort works"
92	atf_set "require.progs" ${order_require_progs}
93}
94
95order_sort_body() {
96	cat > test.x << EOF
97SECTIONS {
98	.data : {
99		*(.data)
100		/* SORT_BY_NAME */
101		SORT(*)(.data.*)
102	}
103}
104EOF
105	order_assert_ascending
106}
107
108################################################################################
109
110atf_test_case multisec
111multisec_head() {
112	atf_set "descr" "check if multiple SECTIONS commands work"
113	atf_set "require.progs" ${order_require_progs}
114}
115
116multisec_body() {
117	cat > test.c << EOF
118#include <sys/cdefs.h>
119char a __section(".data.a") = 'a';
120char b __section(".data.b") = 'b';
121char c __section(".data.c") = 'c';
122EOF
123	atf_check -s exit:0 -o ignore -e ignore cc -c test.c
124
125	cat > test.x << EOF
126SECTIONS {
127	.data : {
128		*(.data)
129		*(.data.a)
130	}
131}
132SECTIONS {
133	.data : {
134		*(.data)
135		*(.data.b)
136	}
137}
138EOF
139	atf_check -s exit:0 -o ignore -e ignore \
140	    ld -r -T test.x -Map test.map -o test.ro test.o
141	extract_section_names test.ro >test.secs
142	extract_symbol_names test.ro >test.syms
143	assert_nosec '\.data\.a'
144	assert_nosec '\.data\.b'
145	assert_sec '\.data\.c'
146}
147
148################################################################################
149
150order_require_progs="cc ld readelf nm sed grep"
151
152order_assert_ascending() {
153	order_assert_order a b c
154}
155
156order_assert_descending() {
157	order_assert_order c b a
158}
159
160order_assert_order() {
161	order_compile
162	order_link
163	{
164		match $1 && match $2 && match $3
165	} <test.syms
166	atf_check test "$?" -eq 0
167}
168
169order_compile() {
170	for i in a b c; do
171		cat > $i.c << EOF
172#include <sys/cdefs.h>
173char $i __section(".data.$i") = '$i';
174EOF
175		atf_check -s exit:0 -o ignore -e ignore cc -c $i.c
176	done
177	cat > test.c << EOF
178int main(void) { return 0; }
179EOF
180	atf_check -s exit:0 -o ignore -e ignore cc -c test.c
181}
182
183order_link() {
184	# c -> b -> a
185	atf_check -s exit:0 -o ignore -e ignore \
186	    ld -r -T test.x -Map test.map -o x.o c.o b.o a.o
187	atf_check -s exit:0 -o ignore -e ignore \
188	    cc -o test test.o x.o
189	extract_symbol_names test |
190	grep '^[abc]$' >test.syms
191}
192
193extract_section_names() {
194	readelf -S "$1" |
195	sed -ne '/\] \./ { s/^.*\] //; s/ .*$//; p }'
196}
197
198extract_symbol_names() {
199	nm -n "$1" |
200	sed -e 's/^.* //'
201}
202
203match() {
204	read line
205	case "$line" in
206	*"$1"*) return 0;
207	esac
208	return 1
209}
210
211assert_sec() {
212	atf_check -s exit:0 -o ignore -e ignore \
213	    grep "^$1\$" test.secs
214}
215
216assert_nosec() {
217	atf_check -s exit:1 -o ignore -e ignore \
218	    grep "^$1\$" test.secs
219}
220
221################################################################################
222
223atf_init_test_cases()
224{
225	atf_add_test_case order_default
226	atf_add_test_case order_merge
227	atf_add_test_case order_reorder
228	atf_add_test_case order_sort
229	atf_add_test_case multisec
230}
231