1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2018 Andrew Turner
5 *
6 * This software was developed by SRI International and the University of
7 * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
8 * ("CTSRD"), as part of the DARPA CRASH research programme.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD$");
34
35#ifndef DSO_LIB
36#include <atf-c.h>
37#endif
38
39#include <crt.h>
40
41typedef void (*func_ptr)(void);
42
43extern volatile int jcr_run;
44extern const func_ptr *jcr_ptr;
45extern const void *jcr_func_ptr;
46extern volatile int ctors_run;
47extern volatile int preinit_array_run;
48extern volatile int preinit_array_state;
49extern volatile int init_array_run;
50extern volatile int init_array_state;
51
52#ifndef DSO_BASE
53volatile int jcr_run;
54const func_ptr *jcr_ptr;
55volatile int ctors_run;
56volatile int preinit_array_run;
57volatile int preinit_array_state = -1;
58volatile int init_array_run;
59volatile int init_array_state = -1;
60
61void _Jv_RegisterClasses(const func_ptr *);
62
63__section(".jcr") __used static func_ptr jcr_func = (func_ptr)1;
64const void *jcr_func_ptr = &jcr_func;
65
66void
67_Jv_RegisterClasses(const func_ptr *jcr)
68{
69
70	jcr_run = 1;
71	jcr_ptr = jcr;
72}
73#endif
74
75#ifndef DSO_LIB
76ATF_TC_WITHOUT_HEAD(jcr_test);
77ATF_TC_BODY(jcr_test, tc)
78{
79
80	ATF_REQUIRE_MSG(jcr_run == 1, ".jcr not run");
81	ATF_REQUIRE_MSG(jcr_ptr == jcr_func_ptr,
82	    "Incorrect pointer passed to _Jv_RegisterClasses");
83}
84#endif
85
86#ifndef DSO_BASE
87static void
88ctors_handler(void)
89{
90
91	ctors_run = 1;
92}
93__section(".ctors") __used static func_ptr ctors_func =
94    &ctors_handler;
95#endif
96
97#ifndef DSO_LIB
98ATF_TC_WITHOUT_HEAD(ctors_test);
99ATF_TC_BODY(ctors_test, tc)
100{
101
102#ifdef HAVE_CTORS
103	ATF_REQUIRE_MSG(ctors_run == 1, ".ctors not run");
104#else
105	ATF_REQUIRE_MSG(ctors_run == 0, ".ctors run");
106#endif
107}
108#endif
109
110#if !defined(DSO_BASE) && !defined(DSO_LIB)
111static void
112preinit_array_handler(void)
113{
114
115	preinit_array_run = 1;
116	preinit_array_state = init_array_run;
117}
118__section(".preinit_array") __used static func_ptr preinit_array_func =
119    &preinit_array_handler;
120#endif
121
122#ifndef DSO_LIB
123ATF_TC_WITHOUT_HEAD(preinit_array_test);
124ATF_TC_BODY(preinit_array_test, tc)
125{
126
127#ifdef DSO_BASE
128	/* Check .preinit_array wasn't run in a DSO */
129	ATF_REQUIRE_MSG(preinit_array_run == 0, ".preinit_array run in DSO");
130#else
131	ATF_REQUIRE_MSG(preinit_array_run == 1, ".preinit_array not run");
132	ATF_REQUIRE_MSG(preinit_array_state == 0,
133	    ".preinit_array was not run before .init_array");
134#endif
135}
136#endif
137
138#ifndef DSO_BASE
139static void
140init_array_handler(void)
141{
142
143	init_array_run = 1;
144	init_array_state = preinit_array_run;
145}
146__section(".init_array") __used static func_ptr init_array_func =
147    &init_array_handler;
148#endif
149
150#ifndef DSO_LIB
151ATF_TC_WITHOUT_HEAD(init_array_test);
152ATF_TC_BODY(init_array_test, tc)
153{
154
155	ATF_REQUIRE_MSG(init_array_run == 1, ".init_array not run");
156#ifndef DSO_BASE
157	ATF_REQUIRE_MSG(init_array_state == 1,
158	    ".init_array was not run after .preinit_array");
159#endif
160}
161
162ATF_TP_ADD_TCS(tp)
163{
164
165	ATF_TP_ADD_TC(tp, jcr_test);
166	ATF_TP_ADD_TC(tp, ctors_test);
167	ATF_TP_ADD_TC(tp, preinit_array_test);
168	ATF_TP_ADD_TC(tp, init_array_test);
169
170	return (atf_no_error());
171}
172#endif
173