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 (at) 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 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