140129Speter/*-
240129Speter * Copyright 1996-1998 John D. Polstra.
340129Speter * All rights reserved.
440129Speter *
540129Speter * Redistribution and use in source and binary forms, with or without
640129Speter * modification, are permitted provided that the following conditions
740129Speter * are met:
840129Speter * 1. Redistributions of source code must retain the above copyright
940129Speter *    notice, this list of conditions and the following disclaimer.
1040129Speter * 2. Redistributions in binary form must reproduce the above copyright
1140129Speter *    notice, this list of conditions and the following disclaimer in the
1240129Speter *    documentation and/or other materials provided with the distribution.
1340129Speter *
1440129Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1540129Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1640129Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1740129Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1840129Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1940129Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2040129Speter * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2140129Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2240129Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2340129Speter * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2440129Speter */
2540129Speter
26115683Sobrien#include <sys/cdefs.h>
27115683Sobrien__FBSDID("$FreeBSD$");
28115683Sobrien
29279211Sjhb#include "opt_cpu.h"
30279211Sjhb
3140129Speter#include <sys/param.h>
32100384Speter#include <sys/kernel.h>
3340129Speter#include <sys/systm.h>
34102808Sjake#include <sys/exec.h>
35102808Sjake#include <sys/imgact.h>
3640129Speter#include <sys/linker.h>
37208453Skib#include <sys/proc.h>
38100384Speter#include <sys/sysent.h>
39100384Speter#include <sys/imgact_elf.h>
40100384Speter#include <sys/syscall.h>
41100384Speter#include <sys/signalvar.h>
42100384Speter#include <sys/vnode.h>
43102808Sjake
44102808Sjake#include <vm/vm.h>
45102808Sjake#include <vm/pmap.h>
46102808Sjake#include <vm/vm_param.h>
47102808Sjake
4840129Speter#include <machine/elf.h>
49100384Speter#include <machine/md_var.h>
50279211Sjhb#include <machine/npx.h>
5140129Speter
52279211Sjhb#if !defined(CPU_DISABLE_SSE) && defined(I686_CPU)
53279211Sjhb#define CPU_ENABLE_SSE
54279211Sjhb#endif
55279211Sjhb
56100384Speterstruct sysentvec elf32_freebsd_sysvec = {
57183322Skib	.sv_size	= SYS_MAXSYSCALL,
58183322Skib	.sv_table	= sysent,
59183322Skib	.sv_mask	= 0,
60183322Skib	.sv_sigsize	= 0,
61183322Skib	.sv_sigtbl	= NULL,
62183322Skib	.sv_errsize	= 0,
63183322Skib	.sv_errtbl	= NULL,
64183322Skib	.sv_transtrap	= NULL,
65183322Skib	.sv_fixup	= __elfN(freebsd_fixup),
66183322Skib	.sv_sendsig	= sendsig,
67183322Skib	.sv_sigcode	= sigcode,
68183322Skib	.sv_szsigcode	= &szsigcode,
69183322Skib	.sv_prepsyscall	= NULL,
70183322Skib	.sv_name	= "FreeBSD ELF32",
71183322Skib	.sv_coredump	= __elfN(coredump),
72183322Skib	.sv_imgact_try	= NULL,
73183322Skib	.sv_minsigstksz	= MINSIGSTKSZ,
74183322Skib	.sv_pagesize	= PAGE_SIZE,
75183322Skib	.sv_minuser	= VM_MIN_ADDRESS,
76183322Skib	.sv_maxuser	= VM_MAXUSER_ADDRESS,
77183322Skib	.sv_usrstack	= USRSTACK,
78183322Skib	.sv_psstrings	= PS_STRINGS,
79183322Skib	.sv_stackprot	= VM_PROT_ALL,
80183322Skib	.sv_copyout_strings	= exec_copyout_strings,
81183322Skib	.sv_setregs	= exec_setregs,
82183322Skib	.sv_fixlimit	= NULL,
83185169Skib	.sv_maxssiz	= NULL,
84237435Skib	.sv_flags	= SV_ABI_FREEBSD | SV_IA32 | SV_ILP32 | SV_SHP,
85208453Skib	.sv_set_syscall_retval = cpu_set_syscall_retval,
86208453Skib	.sv_fetch_syscall_args = cpu_fetch_syscall_args,
87208453Skib	.sv_syscallnames = syscallnames,
88237435Skib	.sv_shared_page_base = SHAREDPAGE,
89237435Skib	.sv_shared_page_len = PAGE_SIZE,
90219405Sdchagin	.sv_schedtail	= NULL,
91293490Sdchagin	.sv_thread_detach = NULL,
92294136Sdchagin	.sv_trap	= NULL,
93100384Speter};
94237435SkibINIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
95100384Speter
96100384Speterstatic Elf32_Brandinfo freebsd_brand_info = {
97183322Skib	.brand		= ELFOSABI_FREEBSD,
98183322Skib	.machine	= EM_386,
99183322Skib	.compat_3_brand	= "FreeBSD",
100183322Skib	.emul_path	= NULL,
101183322Skib	.interp_path	= "/libexec/ld-elf.so.1",
102183322Skib	.sysvec		= &elf32_freebsd_sysvec,
103183322Skib	.interp_newpath	= NULL,
104189771Sdchagin	.brand_note	= &elf32_freebsd_brandnote,
105190708Sdchagin	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE
106183322Skib};
107100384Speter
108197729SbzSYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST,
109100384Speter	(sysinit_cfunc_t) elf32_insert_brand_entry,
110100384Speter	&freebsd_brand_info);
111100384Speter
112123742Speterstatic Elf32_Brandinfo freebsd_brand_oinfo = {
113183322Skib	.brand		= ELFOSABI_FREEBSD,
114183322Skib	.machine	= EM_386,
115183322Skib	.compat_3_brand	= "FreeBSD",
116183322Skib	.emul_path	= NULL,
117183322Skib	.interp_path	= "/usr/libexec/ld-elf.so.1",
118183322Skib	.sysvec		= &elf32_freebsd_sysvec,
119183322Skib	.interp_newpath	= NULL,
120189771Sdchagin	.brand_note	= &elf32_freebsd_brandnote,
121190708Sdchagin	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE
122183322Skib};
123123742Speter
124123742SpeterSYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
125123742Speter	(sysinit_cfunc_t) elf32_insert_brand_entry,
126123742Speter	&freebsd_brand_oinfo);
127123742Speter
128196512Sbzstatic Elf32_Brandinfo kfreebsd_brand_info = {
129196512Sbz	.brand		= ELFOSABI_FREEBSD,
130196512Sbz	.machine	= EM_386,
131196512Sbz	.compat_3_brand	= "FreeBSD",
132196512Sbz	.emul_path	= NULL,
133196512Sbz	.interp_path	= "/lib/ld.so.1",
134196512Sbz	.sysvec		= &elf32_freebsd_sysvec,
135196512Sbz	.interp_newpath	= NULL,
136196512Sbz	.brand_note	= &elf32_kfreebsd_brandnote,
137196653Sbz	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE_MANDATORY
138196512Sbz};
139133464Smarcel
140196512SbzSYSINIT(kelf32, SI_SUB_EXEC, SI_ORDER_ANY,
141196512Sbz	(sysinit_cfunc_t) elf32_insert_brand_entry,
142196512Sbz	&kfreebsd_brand_info);
143196512Sbz
144196512Sbz
145133464Smarcelvoid
146279211Sjhbelf32_dump_thread(struct thread *td, void *dst, size_t *off)
147133464Smarcel{
148279211Sjhb#ifdef CPU_ENABLE_SSE
149279211Sjhb	void *buf;
150279211Sjhb#endif
151279211Sjhb	size_t len;
152279211Sjhb
153279211Sjhb	len = 0;
154279211Sjhb#ifdef CPU_ENABLE_SSE
155279211Sjhb	if (use_xsave) {
156279211Sjhb		if (dst != NULL) {
157279211Sjhb			npxgetregs(td);
158279211Sjhb			len += elf32_populate_note(NT_X86_XSTATE,
159279211Sjhb			    get_pcb_user_save_td(td), dst,
160279211Sjhb			    cpu_max_ext_state_size, &buf);
161279211Sjhb			*(uint64_t *)((char *)buf + X86_XSTATE_XCR0_OFFSET) =
162279211Sjhb			    xsave_mask;
163279211Sjhb		} else
164279211Sjhb			len += elf32_populate_note(NT_X86_XSTATE, NULL, NULL,
165279211Sjhb			    cpu_max_ext_state_size, NULL);
166279211Sjhb	}
167279211Sjhb#endif
168279211Sjhb	*off = len;
169133464Smarcel}
170133464Smarcel
17140130Speter/* Process one elf relocation with addend. */
172109605Sjakestatic int
173129282Speterelf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
174129282Speter    int type, int local, elf_lookup_fn lookup)
17540129Speter{
17640435Speter	Elf_Addr *where;
17741591Sarchie	Elf_Addr addr;
17840435Speter	Elf_Addr addend;
17995410Smarcel	Elf_Word rtype, symidx;
18040435Speter	const Elf_Rel *rel;
18140435Speter	const Elf_Rela *rela;
182288287Skib	int error;
18340129Speter
18440435Speter	switch (type) {
18540435Speter	case ELF_RELOC_REL:
18643314Sdillon		rel = (const Elf_Rel *)data;
18740435Speter		where = (Elf_Addr *) (relocbase + rel->r_offset);
18840435Speter		addend = *where;
18940435Speter		rtype = ELF_R_TYPE(rel->r_info);
19095410Smarcel		symidx = ELF_R_SYM(rel->r_info);
19140435Speter		break;
19240435Speter	case ELF_RELOC_RELA:
19343314Sdillon		rela = (const Elf_Rela *)data;
19440435Speter		where = (Elf_Addr *) (relocbase + rela->r_offset);
19540435Speter		addend = rela->r_addend;
19640435Speter		rtype = ELF_R_TYPE(rela->r_info);
19795410Smarcel		symidx = ELF_R_SYM(rela->r_info);
19840435Speter		break;
19940435Speter	default:
20040435Speter		panic("unknown reloc type %d\n", type);
20140435Speter	}
20240129Speter
203109605Sjake	if (local) {
204109605Sjake		if (rtype == R_386_RELATIVE) {	/* A + B */
205194784Sjeff			addr = elf_relocaddr(lf, relocbase + addend);
206109605Sjake			if (*where != addr)
207109605Sjake				*where = addr;
208109605Sjake		}
209109605Sjake		return (0);
210109605Sjake	}
211109605Sjake
21240435Speter	switch (rtype) {
21340435Speter
21440435Speter		case R_386_NONE:	/* none */
21540129Speter			break;
21640129Speter
21740435Speter		case R_386_32:		/* S + A */
218288287Skib			error = lookup(lf, symidx, 1, &addr);
219288287Skib			if (error != 0)
22040129Speter				return -1;
22140435Speter			addr += addend;
22240129Speter			if (*where != addr)
22340129Speter				*where = addr;
22440129Speter			break;
22540129Speter
22640435Speter		case R_386_PC32:	/* S + A - P */
227288287Skib			error = lookup(lf, symidx, 1, &addr);
228288287Skib			if (error != 0)
22940129Speter				return -1;
23040435Speter			addr += addend - (Elf_Addr)where;
23140129Speter			if (*where != addr)
23240129Speter				*where = addr;
23340129Speter			break;
23440129Speter
23540435Speter		case R_386_COPY:	/* none */
23640129Speter			/*
23740129Speter			 * There shouldn't be copy relocations in kernel
23840129Speter			 * objects.
23940129Speter			 */
24040129Speter			printf("kldload: unexpected R_COPY relocation\n");
24140129Speter			return -1;
24240129Speter			break;
24340129Speter
24440435Speter		case R_386_GLOB_DAT:	/* S */
245288287Skib			error = lookup(lf, symidx, 1, &addr);
246288287Skib			if (error != 0)
24740129Speter				return -1;
24840129Speter			if (*where != addr)
24940129Speter				*where = addr;
25040129Speter			break;
25140129Speter
252109605Sjake		case R_386_RELATIVE:
25340129Speter			break;
25440129Speter
25540129Speter		default:
25640129Speter			printf("kldload: unexpected relocation type %d\n",
25740435Speter			       rtype);
25840129Speter			return -1;
25940129Speter	}
26040129Speter	return(0);
26140129Speter}
262105469Smarcel
263105469Smarcelint
264129282Speterelf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
265129282Speter    elf_lookup_fn lookup)
266109605Sjake{
267109605Sjake
268129282Speter	return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup));
269109605Sjake}
270109605Sjake
271109605Sjakeint
272129282Speterelf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
273129282Speter    int type, elf_lookup_fn lookup)
274109605Sjake{
275109605Sjake
276129282Speter	return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup));
277109605Sjake}
278109605Sjake
279109605Sjakeint
280105469Smarcelelf_cpu_load_file(linker_file_t lf __unused)
281105469Smarcel{
282105469Smarcel
283105469Smarcel	return (0);
284105469Smarcel}
285105469Smarcel
286105469Smarcelint
287105469Smarcelelf_cpu_unload_file(linker_file_t lf __unused)
288105469Smarcel{
289105469Smarcel
290105469Smarcel	return (0);
291105469Smarcel}
292