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