hosted.c (8344B)
1 #include "os/hosted_internal.h" 2 3 static int hosted_add_linux_defines(KitOsHostedPlan* plan, int gnu) { 4 if (kit_os_hosted_add_clang_compat_defines(plan) != 0 || 5 kit_os_hosted_add_define(plan, "__linux__", "1") != 0 || 6 kit_os_hosted_add_define(plan, "__linux", "1") != 0 || 7 kit_os_hosted_add_define(plan, "linux", "1") != 0 || 8 kit_os_hosted_add_define(plan, "__ELF__", "1") != 0) 9 return 1; 10 if (gnu && kit_os_hosted_add_define(plan, "__gnu_linux__", "1") != 0) 11 return 1; 12 return 0; 13 } 14 15 static const char* hosted_glibc_interp(KitArchKind arch) { 16 switch (arch) { 17 case KIT_ARCH_ARM_64: 18 return "/lib/ld-linux-aarch64.so.1"; 19 case KIT_ARCH_X86_64: 20 return "/lib64/ld-linux-x86-64.so.2"; 21 case KIT_ARCH_RV64: 22 return "/lib/ld-linux-riscv64-lp64d.so.1"; 23 default: 24 return NULL; 25 } 26 } 27 28 static const char* hosted_musl_interp(KitArchKind arch) { 29 switch (arch) { 30 case KIT_ARCH_ARM_64: 31 return "/lib/ld-musl-aarch64.so.1"; 32 case KIT_ARCH_X86_64: 33 return "/lib/ld-musl-x86_64.so.1"; 34 case KIT_ARCH_RV64: 35 return "/lib/ld-musl-riscv64.so.1"; 36 default: 37 return NULL; 38 } 39 } 40 41 static int hosted_resolve_linux_musl_static(const KitOsHostedRequest* req, 42 const KitOsHostedDirs* dirs, 43 KitOsHostedPlan* plan) { 44 plan->profile_name = "linux-musl-static"; 45 if (hosted_add_linux_defines(plan, 0) != 0 || 46 kit_os_hosted_add_incdirs(plan, req->host, req->host_user, dirs) != 0) { 47 kit_os_hosted_errf(req->host, req->host_user, req->tool, "out of memory"); 48 return 1; 49 } 50 if (!req->link_inputs) return 0; 51 if (kit_os_hosted_add_required_search( 52 plan->before, &plan->nbefore, KIT_OS_HOSTED_MAX_BEFORE, req, dirs, 53 "crt1.o", KIT_OS_HOSTED_INPUT_OBJECT) != 0 || 54 kit_os_hosted_add_required_search( 55 plan->before, &plan->nbefore, KIT_OS_HOSTED_MAX_BEFORE, req, dirs, 56 "crti.o", KIT_OS_HOSTED_INPUT_OBJECT) != 0) 57 return 1; 58 if (kit_os_hosted_add_required_search( 59 plan->after, &plan->nafter, KIT_OS_HOSTED_MAX_AFTER, req, dirs, 60 "libc.a", KIT_OS_HOSTED_INPUT_ARCHIVE) != 0) 61 return 1; 62 if (kit_os_hosted_add_required_search( 63 plan->final, &plan->nfinal, KIT_OS_HOSTED_MAX_FINAL, req, dirs, 64 "crtn.o", KIT_OS_HOSTED_INPUT_OBJECT) != 0) 65 return 1; 66 return 0; 67 } 68 69 static int hosted_resolve_linux_musl_dynamic(const KitOsHostedRequest* req, 70 const KitOsHostedDirs* dirs, 71 KitOsHostedPlan* plan) { 72 const char* interp = hosted_musl_interp(req->target.arch); 73 if (!interp) { 74 kit_os_hosted_errf(req->host, req->host_user, req->tool, 75 "no hosted musl profile for target architecture"); 76 return 1; 77 } 78 plan->profile_name = "linux-musl-dynamic"; 79 plan->interp_path = interp; 80 if (hosted_add_linux_defines(plan, 0) != 0 || 81 kit_os_hosted_add_incdirs(plan, req->host, req->host_user, dirs) != 0) { 82 kit_os_hosted_errf(req->host, req->host_user, req->tool, "out of memory"); 83 return 1; 84 } 85 if (!req->link_inputs) return 0; 86 if (kit_os_hosted_add_required_search( 87 plan->before, &plan->nbefore, KIT_OS_HOSTED_MAX_BEFORE, req, dirs, 88 "Scrt1.o", KIT_OS_HOSTED_INPUT_OBJECT) != 0 || 89 kit_os_hosted_add_required_search( 90 plan->before, &plan->nbefore, KIT_OS_HOSTED_MAX_BEFORE, req, dirs, 91 "crti.o", KIT_OS_HOSTED_INPUT_OBJECT) != 0) 92 return 1; 93 if (kit_os_hosted_add_required_search( 94 plan->after, &plan->nafter, KIT_OS_HOSTED_MAX_AFTER, req, dirs, 95 "libc.so", KIT_OS_HOSTED_INPUT_DSO) != 0) 96 return 1; 97 if (kit_os_hosted_add_required_search( 98 plan->final, &plan->nfinal, KIT_OS_HOSTED_MAX_FINAL, req, dirs, 99 "crtn.o", KIT_OS_HOSTED_INPUT_OBJECT) != 0) 100 return 1; 101 return 0; 102 } 103 104 static int hosted_resolve_linux_glibc_dynamic(const KitOsHostedRequest* req, 105 const KitOsHostedDirs* dirs, 106 KitOsHostedPlan* plan) { 107 const char* interp = hosted_glibc_interp(req->target.arch); 108 if (!interp) { 109 kit_os_hosted_errf(req->host, req->host_user, req->tool, 110 "no hosted glibc profile for target architecture"); 111 return 1; 112 } 113 plan->profile_name = "linux-glibc-dynamic"; 114 plan->interp_path = interp; 115 if (hosted_add_linux_defines(plan, 1) != 0 || 116 kit_os_hosted_add_incdirs(plan, req->host, req->host_user, dirs) != 0) { 117 kit_os_hosted_errf(req->host, req->host_user, req->tool, "out of memory"); 118 return 1; 119 } 120 if (!req->link_inputs) return 0; 121 if (kit_os_hosted_add_required_search( 122 plan->before, &plan->nbefore, KIT_OS_HOSTED_MAX_BEFORE, req, dirs, 123 "Scrt1.o", KIT_OS_HOSTED_INPUT_OBJECT) != 0 || 124 kit_os_hosted_add_required_search( 125 plan->before, &plan->nbefore, KIT_OS_HOSTED_MAX_BEFORE, req, dirs, 126 "crti.o", KIT_OS_HOSTED_INPUT_OBJECT) != 0) 127 return 1; 128 if (kit_os_hosted_add_required_search( 129 plan->after, &plan->nafter, KIT_OS_HOSTED_MAX_AFTER, req, dirs, 130 "libc.so.6", KIT_OS_HOSTED_INPUT_DSO) != 0 || 131 kit_os_hosted_add_required_search( 132 plan->after, &plan->nafter, KIT_OS_HOSTED_MAX_AFTER, req, dirs, 133 "libc_nonshared.a", KIT_OS_HOSTED_INPUT_ARCHIVE) != 0) 134 return 1; 135 if (kit_os_hosted_add_required_search( 136 plan->final, &plan->nfinal, KIT_OS_HOSTED_MAX_FINAL, req, dirs, 137 "crtn.o", KIT_OS_HOSTED_INPUT_OBJECT) != 0) 138 return 1; 139 return 0; 140 } 141 142 static int hosted_resolve_linux(const KitOsHostedRequest* req, 143 const KitOsHostedDirs* dirs, 144 KitOsHostedPlan* plan) { 145 int has_libc_a, has_libc_so, has_libc_so6, has_glibc_nonshared; 146 if (dirs->nlibdirs == 0) { 147 kit_os_hosted_errf(req->host, req->host_user, req->tool, 148 "Linux hosted profile requires --sysroot or " 149 "KIT_SYSROOT"); 150 return 1; 151 } 152 has_libc_a = 153 kit_os_hosted_libdir_has(req->host, req->host_user, dirs, "libc.a"); 154 has_libc_so = 155 kit_os_hosted_libdir_has(req->host, req->host_user, dirs, "libc.so"); 156 has_libc_so6 = 157 kit_os_hosted_libdir_has(req->host, req->host_user, dirs, "libc.so.6"); 158 has_glibc_nonshared = kit_os_hosted_libdir_has( 159 req->host, req->host_user, dirs, "libc_nonshared.a"); 160 if (!req->static_link && has_libc_so6 && has_glibc_nonshared) 161 return hosted_resolve_linux_glibc_dynamic(req, dirs, plan); 162 if (!req->static_link && has_libc_so) 163 return hosted_resolve_linux_musl_dynamic(req, dirs, plan); 164 if (has_libc_a && !(has_libc_so6 && has_glibc_nonshared)) 165 return hosted_resolve_linux_musl_static(req, dirs, plan); 166 kit_os_hosted_errf(req->host, req->host_user, req->tool, 167 "no supported Linux hosted libc found (searched %u " 168 "library dir(s))", 169 (unsigned)dirs->nlibdirs); 170 return 1; 171 } 172 173 static const char* hosted_linux_inc_triple_sub(KitArchKind arch) { 174 switch (arch) { 175 case KIT_ARCH_ARM_64: 176 return "usr/include/aarch64-linux-gnu"; 177 case KIT_ARCH_X86_64: 178 return "usr/include/x86_64-linux-gnu"; 179 case KIT_ARCH_RV64: 180 return "usr/include/riscv64-linux-gnu"; 181 default: 182 return NULL; 183 } 184 } 185 186 static int hosted_sysroot_layout_linux(KitOsHostedDirs* dirs, 187 KitTargetSpec target, 188 const char* sysroot) { 189 const char* triple = hosted_linux_inc_triple_sub(target.arch); 190 if (kit_os_hosted_dirs_add_inc_join(dirs, sysroot, "usr/include") != 0) 191 return 1; 192 if (triple && kit_os_hosted_dirs_add_inc_join(dirs, sysroot, triple) != 0) 193 return 1; 194 if (kit_os_hosted_dirs_add_lib_join(dirs, sysroot, "usr/lib") != 0) 195 return 1; 196 if (kit_os_hosted_dirs_add_lib_join(dirs, sysroot, "lib") != 0) return 1; 197 if (kit_os_hosted_dirs_add_lib_join(dirs, sysroot, "lib64") != 0) return 1; 198 return 0; 199 } 200 201 const KitOsHostedOps kit_os_linux_hosted_ops = { 202 .obj = KIT_OBJ_ELF, 203 .default_profile = 0, 204 .needs_sysroot_libdir = 0, 205 .resolve = hosted_resolve_linux, 206 .sysroot_layout = hosted_sysroot_layout_linux, 207 };