1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright 1996-1998 John D. Polstra. 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 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 #include <sys/kernel.h> 30 #include <sys/systm.h> 31 #include <sys/exec.h> 32 #include <sys/imgact.h> 33 #include <sys/linker.h> 34 #include <sys/proc.h> 35 #include <sys/reg.h> 36 #include <sys/sysent.h> 37 #include <sys/imgact_elf.h> 38 #include <sys/syscall.h> 39 #include <sys/signalvar.h> 40 #include <sys/vnode.h> 41 42 #include <vm/vm.h> 43 #include <vm/pmap.h> 44 #include <vm/vm_param.h> 45 46 #include <machine/elf.h> 47 #include <machine/fpu.h> 48 #include <machine/md_var.h> 49 50 #include "vdso_offsets.h" 51 52 extern const char _binary_elf_vdso_so_1_start[]; 53 extern const char _binary_elf_vdso_so_1_end[]; 54 extern char _binary_elf_vdso_so_1_size; 55 56 struct sysentvec elf64_freebsd_sysvec_la48 = { 57 .sv_size = SYS_MAXSYSCALL, 58 .sv_table = sysent, 59 .sv_fixup = __elfN(freebsd_fixup), 60 .sv_sendsig = sendsig, 61 .sv_sigcode = _binary_elf_vdso_so_1_start, 62 .sv_szsigcode = (int *)&_binary_elf_vdso_so_1_size, 63 .sv_sigcodeoff = VDSO_SIGCODE_OFFSET, 64 .sv_name = "FreeBSD ELF64", 65 .sv_coredump = __elfN(coredump), 66 .sv_elf_core_osabi = ELFOSABI_FREEBSD, 67 .sv_elf_core_abi_vendor = FREEBSD_ABI_VENDOR, 68 .sv_elf_core_prepare_notes = __elfN(prepare_notes), 69 .sv_minsigstksz = MINSIGSTKSZ, 70 .sv_minuser = VM_MIN_ADDRESS, 71 .sv_maxuser = VM_MAXUSER_ADDRESS_LA48, 72 .sv_usrstack = USRSTACK_LA48, 73 .sv_psstrings = PS_STRINGS_LA48, 74 .sv_psstringssz = sizeof(struct ps_strings), 75 .sv_stackprot = VM_PROT_ALL, 76 .sv_copyout_auxargs = __elfN(freebsd_copyout_auxargs), 77 .sv_copyout_strings = exec_copyout_strings, 78 .sv_setregs = exec_setregs, 79 .sv_fixlimit = NULL, 80 .sv_maxssiz = NULL, 81 .sv_flags = SV_ABI_FREEBSD | SV_ASLR | SV_LP64 | SV_SHP | 82 SV_TIMEKEEP | SV_RNG_SEED_VER | SV_DSO_SIG | 83 SV_SIGSYS, 84 .sv_set_syscall_retval = cpu_set_syscall_retval, 85 .sv_fetch_syscall_args = cpu_fetch_syscall_args, 86 .sv_syscallnames = syscallnames, 87 .sv_shared_page_base = SHAREDPAGE_LA48, 88 .sv_shared_page_len = PAGE_SIZE, 89 .sv_schedtail = NULL, 90 .sv_thread_detach = NULL, 91 .sv_trap = NULL, 92 .sv_onexec_old = exec_onexec_old, 93 .sv_onexit = exit_onexit, 94 .sv_set_fork_retval = x86_set_fork_retval, 95 .sv_regset_begin = SET_BEGIN(__elfN(regset)), 96 .sv_regset_end = SET_LIMIT(__elfN(regset)), 97 }; 98 99 struct sysentvec elf64_freebsd_sysvec_la57 = { 100 .sv_size = SYS_MAXSYSCALL, 101 .sv_table = sysent, 102 .sv_fixup = __elfN(freebsd_fixup), 103 .sv_sendsig = sendsig, 104 .sv_sigcode = _binary_elf_vdso_so_1_start, 105 .sv_szsigcode = (int *)&_binary_elf_vdso_so_1_size, 106 .sv_sigcodeoff = VDSO_SIGCODE_OFFSET, 107 .sv_name = "FreeBSD ELF64", 108 .sv_coredump = __elfN(coredump), 109 .sv_elf_core_osabi = ELFOSABI_FREEBSD, 110 .sv_elf_core_abi_vendor = FREEBSD_ABI_VENDOR, 111 .sv_elf_core_prepare_notes = __elfN(prepare_notes), 112 .sv_minsigstksz = MINSIGSTKSZ, 113 .sv_minuser = VM_MIN_ADDRESS, 114 .sv_maxuser = VM_MAXUSER_ADDRESS_LA57, 115 .sv_usrstack = USRSTACK_LA57, 116 .sv_psstrings = PS_STRINGS_LA57, 117 .sv_psstringssz = sizeof(struct ps_strings), 118 .sv_stackprot = VM_PROT_ALL, 119 .sv_copyout_auxargs = __elfN(freebsd_copyout_auxargs), 120 .sv_copyout_strings = exec_copyout_strings, 121 .sv_setregs = exec_setregs, 122 .sv_fixlimit = NULL, 123 .sv_maxssiz = NULL, 124 .sv_flags = SV_ABI_FREEBSD | SV_ASLR | SV_LP64 | SV_SHP | 125 SV_TIMEKEEP | SV_RNG_SEED_VER | SV_DSO_SIG | 126 SV_SIGSYS, 127 .sv_set_syscall_retval = cpu_set_syscall_retval, 128 .sv_fetch_syscall_args = cpu_fetch_syscall_args, 129 .sv_syscallnames = syscallnames, 130 .sv_shared_page_base = SHAREDPAGE_LA57, 131 .sv_shared_page_len = PAGE_SIZE, 132 .sv_schedtail = NULL, 133 .sv_thread_detach = NULL, 134 .sv_trap = NULL, 135 .sv_onexec_old = exec_onexec_old, 136 .sv_onexit = exit_onexit, 137 .sv_set_fork_retval= x86_set_fork_retval, 138 .sv_regset_begin = SET_BEGIN(__elfN(regset)), 139 .sv_regset_end = SET_LIMIT(__elfN(regset)), 140 }; 141 142 static void 143 amd64_init_sysvecs(void *arg) 144 { 145 amd64_lower_shared_page(&elf64_freebsd_sysvec_la48); 146 if (la57) { 147 exec_sysvec_init(&elf64_freebsd_sysvec_la57); 148 exec_sysvec_init_secondary(&elf64_freebsd_sysvec_la57, 149 &elf64_freebsd_sysvec_la48); 150 } else { 151 exec_sysvec_init(&elf64_freebsd_sysvec_la48); 152 } 153 } 154 SYSINIT(elf64_sysvec, SI_SUB_EXEC, SI_ORDER_ANY, amd64_init_sysvecs, NULL); 155 156 void 157 amd64_lower_shared_page(struct sysentvec *sv) 158 { 159 if (hw_lower_amd64_sharedpage != 0) { 160 sv->sv_maxuser -= PAGE_SIZE; 161 sv->sv_shared_page_base -= PAGE_SIZE; 162 sv->sv_usrstack -= PAGE_SIZE; 163 sv->sv_psstrings -= PAGE_SIZE; 164 } 165 } 166 167 static bool 168 freebsd_brand_info_la57_img_compat(const struct image_params *imgp, 169 const int32_t *osrel __unused, const uint32_t *fctl0) 170 { 171 if ((imgp->proc->p_md.md_flags & P_MD_LA57) != 0) 172 return (true); 173 if (fctl0 != NULL && (*fctl0 & NT_FREEBSD_FCTL_LA57) != 0) 174 return (true); 175 if (fctl0 == NULL || (*fctl0 & NT_FREEBSD_FCTL_LA48) != 0) 176 return (false); 177 if ((imgp->proc->p_md.md_flags & P_MD_LA48) != 0) 178 return (false); 179 return (!prefer_uva_la48); 180 } 181 182 static Elf64_Brandinfo freebsd_brand_info_la48 = { 183 .brand = ELFOSABI_FREEBSD, 184 .machine = EM_X86_64, 185 .compat_3_brand = "FreeBSD", 186 .interp_path = "/libexec/ld-elf.so.1", 187 .sysvec = &elf64_freebsd_sysvec_la48, 188 .interp_newpath = NULL, 189 .brand_note = &elf64_freebsd_brandnote, 190 .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE, 191 }; 192 193 static Elf64_Brandinfo freebsd_brand_info_la57 = { 194 .brand = ELFOSABI_FREEBSD, 195 .machine = EM_X86_64, 196 .compat_3_brand = "FreeBSD", 197 .interp_path = "/libexec/ld-elf.so.1", 198 .sysvec = &elf64_freebsd_sysvec_la57, 199 .interp_newpath = NULL, 200 .brand_note = &elf64_freebsd_brandnote, 201 .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE, 202 .header_supported = freebsd_brand_info_la57_img_compat, 203 }; 204 205 static void 206 sysinit_register_elf64_brand_entries(void *arg __unused) 207 { 208 /* 209 * _57 must go first so it can either claim the image or hand 210 * it to _48. 211 */ 212 if (la57) 213 elf64_insert_brand_entry(&freebsd_brand_info_la57); 214 elf64_insert_brand_entry(&freebsd_brand_info_la48); 215 } 216 SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_FIRST, 217 sysinit_register_elf64_brand_entries, NULL); 218 219 static Elf64_Brandinfo freebsd_brand_oinfo = { 220 .brand = ELFOSABI_FREEBSD, 221 .machine = EM_X86_64, 222 .compat_3_brand = "FreeBSD", 223 .interp_path = "/usr/libexec/ld-elf.so.1", 224 .sysvec = &elf64_freebsd_sysvec_la48, 225 .interp_newpath = NULL, 226 .brand_note = &elf64_freebsd_brandnote, 227 .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE 228 }; 229 230 SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY, 231 (sysinit_cfunc_t)elf64_insert_brand_entry, &freebsd_brand_oinfo); 232 233 static Elf64_Brandinfo kfreebsd_brand_info = { 234 .brand = ELFOSABI_FREEBSD, 235 .machine = EM_X86_64, 236 .compat_3_brand = "FreeBSD", 237 .interp_path = "/lib/ld-kfreebsd-x86-64.so.1", 238 .sysvec = &elf64_freebsd_sysvec_la48, 239 .interp_newpath = NULL, 240 .brand_note = &elf64_kfreebsd_brandnote, 241 .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE_MANDATORY 242 }; 243 244 SYSINIT(kelf64, SI_SUB_EXEC, SI_ORDER_ANY, 245 (sysinit_cfunc_t)elf64_insert_brand_entry, &kfreebsd_brand_info); 246 247 void 248 elf64_dump_thread(struct thread *td, void *dst, size_t *off) 249 { 250 void *buf; 251 size_t len; 252 253 len = 0; 254 if (use_xsave) { 255 if (dst != NULL) { 256 fpugetregs(td); 257 len += elf64_populate_note(NT_X86_XSTATE, 258 get_pcb_user_save_td(td), dst, 259 cpu_max_ext_state_size, &buf); 260 *(uint64_t *)((char *)buf + X86_XSTATE_XCR0_OFFSET) = 261 xsave_mask; 262 } else 263 len += elf64_populate_note(NT_X86_XSTATE, NULL, NULL, 264 cpu_max_ext_state_size, NULL); 265 } 266 *off = len; 267 } 268 269 bool 270 elf_is_ifunc_reloc(Elf_Size r_info) 271 { 272 273 return (ELF_R_TYPE(r_info) == R_X86_64_IRELATIVE); 274 } 275 276 /* Process one elf relocation with addend. */ 277 static int 278 elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, 279 int type, bool late_ifunc, elf_lookup_fn lookup) 280 { 281 Elf64_Addr *where, val; 282 Elf32_Addr *where32, val32; 283 Elf_Addr addr; 284 Elf_Addr addend; 285 Elf_Size rtype, symidx; 286 const Elf_Rel *rel; 287 const Elf_Rela *rela; 288 int error; 289 290 switch (type) { 291 case ELF_RELOC_REL: 292 rel = (const Elf_Rel *)data; 293 where = (Elf_Addr *) (relocbase + rel->r_offset); 294 rtype = ELF_R_TYPE(rel->r_info); 295 symidx = ELF_R_SYM(rel->r_info); 296 /* Addend is 32 bit on 32 bit relocs */ 297 switch (rtype) { 298 case R_X86_64_PC32: 299 case R_X86_64_32S: 300 case R_X86_64_PLT32: 301 addend = *(Elf32_Addr *)where; 302 break; 303 default: 304 addend = *where; 305 break; 306 } 307 break; 308 case ELF_RELOC_RELA: 309 rela = (const Elf_Rela *)data; 310 where = (Elf_Addr *) (relocbase + rela->r_offset); 311 addend = rela->r_addend; 312 rtype = ELF_R_TYPE(rela->r_info); 313 symidx = ELF_R_SYM(rela->r_info); 314 break; 315 default: 316 panic("unknown reloc type %d\n", type); 317 } 318 319 if (late_ifunc) { 320 KASSERT(type == ELF_RELOC_RELA, 321 ("Only RELA ifunc relocations are supported")); 322 if (rtype != R_X86_64_IRELATIVE) 323 return (0); 324 } 325 326 switch (rtype) { 327 case R_X86_64_NONE: /* none */ 328 break; 329 330 case R_X86_64_64: /* S + A */ 331 error = lookup(lf, symidx, 1, &addr); 332 val = addr + addend; 333 if (error != 0) 334 return (-1); 335 if (*where != val) 336 *where = val; 337 break; 338 339 case R_X86_64_PC32: /* S + A - P */ 340 case R_X86_64_PLT32: /* L + A - P, L is PLT location for 341 the symbol, which we treat as S */ 342 error = lookup(lf, symidx, 1, &addr); 343 where32 = (Elf32_Addr *)where; 344 val32 = (Elf32_Addr)(addr + addend - (Elf_Addr)where); 345 if (error != 0) 346 return (-1); 347 if (*where32 != val32) 348 *where32 = val32; 349 break; 350 351 case R_X86_64_32S: /* S + A sign extend */ 352 error = lookup(lf, symidx, 1, &addr); 353 val32 = (Elf32_Addr)(addr + addend); 354 where32 = (Elf32_Addr *)where; 355 if (error != 0) 356 return (-1); 357 if (*where32 != val32) 358 *where32 = val32; 359 break; 360 361 case R_X86_64_COPY: /* none */ 362 /* 363 * There shouldn't be copy relocations in kernel 364 * objects. 365 */ 366 printf("kldload: unexpected R_COPY relocation, " 367 "symbol index %ld\n", symidx); 368 return (-1); 369 370 case R_X86_64_GLOB_DAT: /* S */ 371 case R_X86_64_JMP_SLOT: /* XXX need addend + offset */ 372 error = lookup(lf, symidx, 1, &addr); 373 if (error != 0) 374 return (-1); 375 if (*where != addr) 376 *where = addr; 377 break; 378 379 case R_X86_64_RELATIVE: /* B + A */ 380 addr = elf_relocaddr(lf, relocbase + addend); 381 val = addr; 382 if (*where != val) 383 *where = val; 384 break; 385 386 case R_X86_64_IRELATIVE: 387 addr = relocbase + addend; 388 val = ((Elf64_Addr (*)(void))addr)(); 389 if (*where != val) 390 *where = val; 391 break; 392 393 default: 394 printf("kldload: unexpected relocation type %ld, " 395 "symbol index %ld\n", rtype, symidx); 396 return (-1); 397 } 398 return (0); 399 } 400 401 int 402 elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, 403 elf_lookup_fn lookup) 404 { 405 406 return (elf_reloc_internal(lf, relocbase, data, type, false, lookup)); 407 } 408 409 int 410 elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, 411 int type, elf_lookup_fn lookup) 412 { 413 414 return (elf_reloc_internal(lf, relocbase, data, type, false, lookup)); 415 } 416 417 int 418 elf_reloc_late(linker_file_t lf, Elf_Addr relocbase, const void *data, 419 int type, elf_lookup_fn lookup) 420 { 421 422 return (elf_reloc_internal(lf, relocbase, data, type, true, lookup)); 423 } 424 425 int 426 elf_cpu_load_file(linker_file_t lf __unused) 427 { 428 429 return (0); 430 } 431 432 int 433 elf_cpu_unload_file(linker_file_t lf __unused) 434 { 435 436 return (0); 437 } 438 439 int 440 elf_cpu_parse_dynamic(caddr_t loadbase __unused, Elf_Dyn *dynamic __unused) 441 { 442 443 return (0); 444 } 445