Home | History | Annotate | Line # | Download | only in driver
      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