1 /*	$Id: platform.c,v 1.5 2012/08/09 11:41:28 ragge Exp $	*/
2 
3 /*-
4  * Copyright (c) 2011 Joerg Sonnenberger <joerg@NetBSD.org>.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
22  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <string.h>
33 
34 #include "driver.h"
35 #include "config.h"
36 
37 #include "ccconfig.h"
38 
39 #ifndef NEW_DRIVER_CFG
40 #define	USE_OLD_DRIVER_CFG
41 #endif
42 
43 #define _MKS(x)		#x
44 #define MKS(x)		_MKS(x)
45 
46 #ifndef PREPROCESSOR
47 #define PREPROCESSOR	"cpp"
48 #endif
49 
50 #ifndef COMPILER
51 #define COMPILER	"ccom"
52 #endif
53 
54 #ifndef ASSEMBLER
55 #define ASSEMBLER	"as"
56 #endif
57 
58 #ifndef LINKER
59 #define LINKER		"ld"
60 #endif
61 
62 enum architecture {
63 	ARCH_ANY,
64 	ARCH_I386,
65 	ARCH_X86_64
66 };
67 
68 static const struct {
69 	enum architecture arch;
70 	const char *name;
71 } arch_mapping[] = {
72 #ifdef USE_OLD_DRIVER_CFG
73 	{ ARCH_ANY, TARGMACH },
74 #else
75 	{ ARCH_I386, "i386" },
76 	{ ARCH_X86_64, "x86_64" } ,
77 #endif
78 };
79 
80 enum os {
81 	OS_ANY,
82 	OS_NETBSD,
83 	OS_LINUX
84 };
85 
86 static const struct {
87 	enum os os;
88 	const char *name;
89 } os_mapping[] = {
90 #ifdef USE_OLD_DRIVER_CFG
91 	{ OS_ANY, TARGOS },
92 #else
93 	{ OS_NETBSD, "netbsd" },
94 	{ OS_LINUX, "linux" },
95 #endif
96 };
97 
98 struct platform_specific {
99 	enum architecture arch;
100 	enum os os;
101 	const char * const *values;
102 };
103 
104 #ifndef USE_OLD_DRIVER_CFG
105 static const char * const early_program_csu_values0[] = { "crt0.o", NULL };
106 static const char * const early_program_csu_values1[] = { "crt1.o", NULL };
107 #else
108 static const char * const early_program_csu_values2[] = {
109 	CRT0FILE, NULL
110 };
111 #endif
112 
113 static const struct platform_specific early_program_csu[] = {
114 #ifdef USE_OLD_DRIVER_CFG
115 	{ ARCH_ANY, OS_ANY, early_program_csu_values2 },
116 #else
117 	{ ARCH_ANY, OS_NETBSD, early_program_csu_values0 },
118 	{ ARCH_ANY, OS_LINUX, early_program_csu_values1 },
119 #endif
120 };
121 
122 static const char * const late_program_csu_values0[] = {
123     "crtend.o", "crtn.o", NULL
124 };
125 static const struct platform_specific late_program_csu[] = {
126     { ARCH_ANY, OS_ANY, late_program_csu_values0 },
127 };
128 
129 static const char * const early_dso_csu_values0[] = {
130     "crtio", "crtbeginS.o", NULL
131 };
132 static const struct platform_specific early_dso_csu[] = {
133     { ARCH_ANY, OS_ANY, early_dso_csu_values0 },
134 };
135 
136 static const char * const late_dso_csu_values0[] = {
137     "crtendS.o", "crtn.o", NULL
138 };
139 static const struct platform_specific late_dso_csu[] = {
140     { ARCH_ANY, OS_ANY, late_dso_csu_values0 },
141 };
142 
143 static const char * const predefined_macros_values0[] = {
144     "-D__x86_64__", "-D__x86_64", "-D__amd64__", "-D__amd64", NULL
145 };
146 static const char * const predefined_macros_values1[] = {
147     "-D__NetBSD__", "-D__ELF__", NULL
148 };
149 static const char * const predefined_macros_values2[] = {
150     "-D__linux__", "-D__ELF__", NULL
151 };
152 static const char * const predefined_macros_values3[] = {
153     "-D__i386__", NULL
154 };
155 static const char * const predefined_macros_values4[] = {
156     "-D__PCC__=" MKS(PCC_MAJOR),
157     "-D__PCC_MINOR__=" MKS(PCC_MINOR),
158     "-D__PCC_MINORMINOR__=" MKS(PCC_MINORMINOR),
159     "-D__VERSION__=" MKS(VERSSTR),
160     "-D__STDC_ISO_10646__=200009L",
161     NULL
162 };
163 static const char * const predefined_macros_values5[] = {
164     "-D__GNUC__=4",
165     "-D__GNUC_MINOR__=3",
166     "-D__GNUC_PATCHLEVEL__=1",
167     "-D__GNUC_STDC_INLINE__=1",
168     NULL
169 };
170 static const struct platform_specific predefined_macros[] = {
171     { ARCH_X86_64, OS_ANY, predefined_macros_values0 },
172     { ARCH_ANY, OS_NETBSD, predefined_macros_values1 },
173     { ARCH_ANY, OS_LINUX, predefined_macros_values2 },
174     { ARCH_I386, OS_ANY, predefined_macros_values3 },
175     { ARCH_ANY, OS_ANY, predefined_macros_values4 },
176     { ARCH_ANY, OS_ANY, predefined_macros_values5 },
177 };
178 
179 static const char * const early_linker_values0[] = {
180     "-dynamic-linker", "/libexec/ld.elf_so", NULL
181 };
182 static const char * const early_linker_values1[] = {
183     "-m", "elf_i386", NULL
184 };
185 static const char * const early_linker_values2[] = {
186     "-m", "elf_x86_64", NULL
187 };
188 static const char * const early_linker_values3[] = {
189     "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2", NULL
190 };
191 static const char * const early_linker_values4[] = {
192     "-m", "elf_i386", NULL
193 };
194 static const char * const early_linker_values5[] = {
195     "-m", "elf_x86_64", NULL
196 };
197 static const struct platform_specific early_linker[] = {
198     { ARCH_ANY, OS_NETBSD, early_linker_values0 },
199     { ARCH_I386, OS_NETBSD, early_linker_values1 },
200     { ARCH_X86_64, OS_NETBSD, early_linker_values2 },
201     { ARCH_ANY, OS_LINUX, early_linker_values3 },
202     { ARCH_I386, OS_LINUX, early_linker_values4 },
203     { ARCH_X86_64, OS_LINUX, early_linker_values5 },
204 };
205 
206 static const char * const sysincdir_list_values0[] = {
207     "=/usr/include", NULL
208 };
209 static const char * const sysincdir_list_values1[] = {
210     /* XXX fix up for libpcc? */
211     "=/usr/lib/gcc/x86_64-linux-gnu/4.4/include", NULL
212 };
213 static const struct platform_specific sysincdir_list[] = {
214     { ARCH_ANY, OS_ANY, sysincdir_list_values0 },
215     { ARCH_X86_64, OS_LINUX, sysincdir_list_values1 },
216 };
217 
218 static const char * const crtdir_list_values0[] = {
219     "=/usr/lib/i386", "=/usr/lib", NULL
220 };
221 static const char * const crtdir_list_values1[] = {
222     "=/usr/lib", NULL
223 };
224 static const char * const crtdir_list_values2[] = {
225     "=/usr/lib64", "=/usr/lib/gcc/x86_64-linux-gnu/4.4", NULL
226 };
227 static const struct platform_specific crtdir_list[] = {
228     { ARCH_I386, OS_NETBSD, crtdir_list_values0 },
229     { ARCH_X86_64, OS_NETBSD, crtdir_list_values1 },
230     { ARCH_X86_64, OS_LINUX, crtdir_list_values2 },
231 };
232 
233 static const char * const stdlib_list_values0[] = {
234     "-L/usr/lib/gcc/x86_64-linux-gnu/4.4", NULL
235 };
236 static const char * const stdlib_list_values1[] = {
237     "-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed",
238     "-lc", "-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed", NULL
239 };
240 static const struct platform_specific stdlib_list[] = {
241     { ARCH_X86_64, OS_LINUX, stdlib_list_values0 },
242     { ARCH_ANY, OS_ANY, stdlib_list_values1 },
243 };
244 
245 static const char * const program_dirs_values0[] = {
246     LIBEXECDIR, NULL
247 };
248 static const struct platform_specific program_dirs[] = {
249     { ARCH_ANY, OS_ANY, program_dirs_values0 },
250 };
251 
252 #define	ARRAYLEN(a)	(sizeof(a) / sizeof((a)[0]))
253 #define	ARRAYPAIR(a)	a, ARRAYLEN(a)
254 
255 static const struct {
256 	const struct platform_specific *initializer;
257 	size_t len;
258 	struct strlist *list;
259 } platform_specific_inits[] = {
260     { ARRAYPAIR(early_program_csu), &early_program_csu_files },
261     { ARRAYPAIR(late_program_csu), &late_program_csu_files },
262     { ARRAYPAIR(early_dso_csu), &early_dso_csu_files },
263     { ARRAYPAIR(late_dso_csu), &late_dso_csu_files },
264     { ARRAYPAIR(predefined_macros), &preprocessor_flags },
265     { ARRAYPAIR(early_linker), &early_linker_flags },
266     { ARRAYPAIR(sysincdir_list), &sysincdirs },
267     { ARRAYPAIR(crtdir_list), &crtdirs },
268     { ARRAYPAIR(stdlib_list), &stdlib_flags },
269     { ARRAYPAIR(program_dirs), &progdirs },
270 };
271 
272 void
init_platform_specific(const char * os_name,const char * arch_name)273 init_platform_specific(const char *os_name, const char *arch_name)
274 {
275 	enum os os;
276 	enum architecture arch;
277 	size_t i, j, len;
278 	const struct platform_specific *initializer;
279 	struct strlist *l;
280 
281 	os = OS_ANY;
282 	for (i = 0; i < ARRAYLEN(os_mapping); ++i) {
283 		if (strcmp(os_mapping[i].name, os_name) == 0) {
284 			os = os_mapping[i].os;
285 			break;
286 		}
287 	}
288 	if (os == OS_ANY)
289 		error("unknown Operating System: %s", os_name);
290 
291 	arch = ARCH_ANY;
292 	for (i = 0; i < ARRAYLEN(arch_mapping); ++i) {
293 		if (strcmp(arch_mapping[i].name, arch_name) == 0) {
294 			arch = arch_mapping[i].arch;
295 			break;
296 		}
297 	}
298 	if (arch == ARCH_ANY)
299 		error("unknown architecture: %s", arch_name);
300 
301 	for (i = 0; i < ARRAYLEN(platform_specific_inits); ++i) {
302 		initializer = platform_specific_inits[i].initializer;
303 		len = platform_specific_inits[i].len;
304 		l = platform_specific_inits[i].list;
305 		for (j = 0; j < len; ++j) {
306 			if (initializer[j].arch != arch &&
307 			    initializer[j].arch != ARCH_ANY)
308 				continue;
309 			if (initializer[j].os != os &&
310 			    initializer[j].os != OS_ANY)
311 				continue;
312 			strlist_append_array(l, initializer[j].values);
313 		}
314 	}
315 
316 	preprocessor = PREPROCESSOR;
317 	compiler = COMPILER;
318 	assembler = ASSEMBLER;
319 	linker = LINKER;
320 }
321