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