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
2940129Speter#include <sys/param.h>
30100384Speter#include <sys/kernel.h>
3140129Speter#include <sys/systm.h>
32102808Sjake#include <sys/exec.h>
33102808Sjake#include <sys/imgact.h>
3440129Speter#include <sys/linker.h>
35208453Skib#include <sys/proc.h>
36100384Speter#include <sys/sysent.h>
37100384Speter#include <sys/imgact_elf.h>
38100384Speter#include <sys/syscall.h>
39100384Speter#include <sys/signalvar.h>
40100384Speter#include <sys/vnode.h>
41102808Sjake
42102808Sjake#include <vm/vm.h>
43102808Sjake#include <vm/pmap.h>
44102808Sjake#include <vm/vm_param.h>
45102808Sjake
4640129Speter#include <machine/elf.h>
47100384Speter#include <machine/md_var.h>
4840129Speter
49100384Speterstruct sysentvec elf32_freebsd_sysvec = {
50183322Skib	.sv_size	= SYS_MAXSYSCALL,
51183322Skib	.sv_table	= sysent,
52183322Skib	.sv_mask	= 0,
53183322Skib	.sv_sigsize	= 0,
54183322Skib	.sv_sigtbl	= NULL,
55183322Skib	.sv_errsize	= 0,
56183322Skib	.sv_errtbl	= NULL,
57183322Skib	.sv_transtrap	= NULL,
58183322Skib	.sv_fixup	= __elfN(freebsd_fixup),
59183322Skib	.sv_sendsig	= sendsig,
60183322Skib	.sv_sigcode	= sigcode,
61183322Skib	.sv_szsigcode	= &szsigcode,
62183322Skib	.sv_prepsyscall	= NULL,
63183322Skib	.sv_name	= "FreeBSD ELF32",
64183322Skib	.sv_coredump	= __elfN(coredump),
65183322Skib	.sv_imgact_try	= NULL,
66183322Skib	.sv_minsigstksz	= MINSIGSTKSZ,
67183322Skib	.sv_pagesize	= PAGE_SIZE,
68183322Skib	.sv_minuser	= VM_MIN_ADDRESS,
69183322Skib	.sv_maxuser	= VM_MAXUSER_ADDRESS,
70183322Skib	.sv_usrstack	= USRSTACK,
71183322Skib	.sv_psstrings	= PS_STRINGS,
72183322Skib	.sv_stackprot	= VM_PROT_ALL,
73183322Skib	.sv_copyout_strings	= exec_copyout_strings,
74183322Skib	.sv_setregs	= exec_setregs,
75183322Skib	.sv_fixlimit	= NULL,
76185169Skib	.sv_maxssiz	= NULL,
77237435Skib	.sv_flags	= SV_ABI_FREEBSD | SV_IA32 | SV_ILP32 | SV_SHP,
78208453Skib	.sv_set_syscall_retval = cpu_set_syscall_retval,
79208453Skib	.sv_fetch_syscall_args = cpu_fetch_syscall_args,
80208453Skib	.sv_syscallnames = syscallnames,
81237435Skib	.sv_shared_page_base = SHAREDPAGE,
82237435Skib	.sv_shared_page_len = PAGE_SIZE,
83219405Sdchagin	.sv_schedtail	= NULL,
84100384Speter};
85237435SkibINIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
86100384Speter
87100384Speterstatic Elf32_Brandinfo freebsd_brand_info = {
88183322Skib	.brand		= ELFOSABI_FREEBSD,
89183322Skib	.machine	= EM_386,
90183322Skib	.compat_3_brand	= "FreeBSD",
91183322Skib	.emul_path	= NULL,
92183322Skib	.interp_path	= "/libexec/ld-elf.so.1",
93183322Skib	.sysvec		= &elf32_freebsd_sysvec,
94183322Skib	.interp_newpath	= NULL,
95189771Sdchagin	.brand_note	= &elf32_freebsd_brandnote,
96190708Sdchagin	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE
97183322Skib};
98100384Speter
99197729SbzSYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST,
100100384Speter	(sysinit_cfunc_t) elf32_insert_brand_entry,
101100384Speter	&freebsd_brand_info);
102100384Speter
103123742Speterstatic Elf32_Brandinfo freebsd_brand_oinfo = {
104183322Skib	.brand		= ELFOSABI_FREEBSD,
105183322Skib	.machine	= EM_386,
106183322Skib	.compat_3_brand	= "FreeBSD",
107183322Skib	.emul_path	= NULL,
108183322Skib	.interp_path	= "/usr/libexec/ld-elf.so.1",
109183322Skib	.sysvec		= &elf32_freebsd_sysvec,
110183322Skib	.interp_newpath	= NULL,
111189771Sdchagin	.brand_note	= &elf32_freebsd_brandnote,
112190708Sdchagin	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE
113183322Skib};
114123742Speter
115123742SpeterSYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
116123742Speter	(sysinit_cfunc_t) elf32_insert_brand_entry,
117123742Speter	&freebsd_brand_oinfo);
118123742Speter
119196512Sbzstatic Elf32_Brandinfo kfreebsd_brand_info = {
120196512Sbz	.brand		= ELFOSABI_FREEBSD,
121196512Sbz	.machine	= EM_386,
122196512Sbz	.compat_3_brand	= "FreeBSD",
123196512Sbz	.emul_path	= NULL,
124196512Sbz	.interp_path	= "/lib/ld.so.1",
125196512Sbz	.sysvec		= &elf32_freebsd_sysvec,
126196512Sbz	.interp_newpath	= NULL,
127196512Sbz	.brand_note	= &elf32_kfreebsd_brandnote,
128196653Sbz	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE_MANDATORY
129196512Sbz};
130133464Smarcel
131196512SbzSYSINIT(kelf32, SI_SUB_EXEC, SI_ORDER_ANY,
132196512Sbz	(sysinit_cfunc_t) elf32_insert_brand_entry,
133196512Sbz	&kfreebsd_brand_info);
134196512Sbz
135196512Sbz
136133464Smarcelvoid
137133464Smarcelelf32_dump_thread(struct thread *td __unused, void *dst __unused,
138133464Smarcel    size_t *off __unused)
139133464Smarcel{
140133464Smarcel}
141133464Smarcel
142133464Smarcel
14340130Speter/* Process one elf relocation with addend. */
144109605Sjakestatic int
145129282Speterelf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
146129282Speter    int type, int local, elf_lookup_fn lookup)
14740129Speter{
14840435Speter	Elf_Addr *where;
14941591Sarchie	Elf_Addr addr;
15040435Speter	Elf_Addr addend;
15195410Smarcel	Elf_Word rtype, symidx;
15240435Speter	const Elf_Rel *rel;
15340435Speter	const Elf_Rela *rela;
15440129Speter
15540435Speter	switch (type) {
15640435Speter	case ELF_RELOC_REL:
15743314Sdillon		rel = (const Elf_Rel *)data;
15840435Speter		where = (Elf_Addr *) (relocbase + rel->r_offset);
15940435Speter		addend = *where;
16040435Speter		rtype = ELF_R_TYPE(rel->r_info);
16195410Smarcel		symidx = ELF_R_SYM(rel->r_info);
16240435Speter		break;
16340435Speter	case ELF_RELOC_RELA:
16443314Sdillon		rela = (const Elf_Rela *)data;
16540435Speter		where = (Elf_Addr *) (relocbase + rela->r_offset);
16640435Speter		addend = rela->r_addend;
16740435Speter		rtype = ELF_R_TYPE(rela->r_info);
16895410Smarcel		symidx = ELF_R_SYM(rela->r_info);
16940435Speter		break;
17040435Speter	default:
17140435Speter		panic("unknown reloc type %d\n", type);
17240435Speter	}
17340129Speter
174109605Sjake	if (local) {
175109605Sjake		if (rtype == R_386_RELATIVE) {	/* A + B */
176194784Sjeff			addr = elf_relocaddr(lf, relocbase + addend);
177109605Sjake			if (*where != addr)
178109605Sjake				*where = addr;
179109605Sjake		}
180109605Sjake		return (0);
181109605Sjake	}
182109605Sjake
18340435Speter	switch (rtype) {
18440435Speter
18540435Speter		case R_386_NONE:	/* none */
18640129Speter			break;
18740129Speter
18840435Speter		case R_386_32:		/* S + A */
189129282Speter			addr = lookup(lf, symidx, 1);
19054952Seivind			if (addr == 0)
19140129Speter				return -1;
19240435Speter			addr += addend;
19340129Speter			if (*where != addr)
19440129Speter				*where = addr;
19540129Speter			break;
19640129Speter
19740435Speter		case R_386_PC32:	/* S + A - P */
198129282Speter			addr = lookup(lf, symidx, 1);
19954952Seivind			if (addr == 0)
20040129Speter				return -1;
20140435Speter			addr += addend - (Elf_Addr)where;
20240129Speter			if (*where != addr)
20340129Speter				*where = addr;
20440129Speter			break;
20540129Speter
20640435Speter		case R_386_COPY:	/* none */
20740129Speter			/*
20840129Speter			 * There shouldn't be copy relocations in kernel
20940129Speter			 * objects.
21040129Speter			 */
21140129Speter			printf("kldload: unexpected R_COPY relocation\n");
21240129Speter			return -1;
21340129Speter			break;
21440129Speter
21540435Speter		case R_386_GLOB_DAT:	/* S */
216129282Speter			addr = lookup(lf, symidx, 1);
21754952Seivind			if (addr == 0)
21840129Speter				return -1;
21940129Speter			if (*where != addr)
22040129Speter				*where = addr;
22140129Speter			break;
22240129Speter
223109605Sjake		case R_386_RELATIVE:
22440129Speter			break;
22540129Speter
22640129Speter		default:
22740129Speter			printf("kldload: unexpected relocation type %d\n",
22840435Speter			       rtype);
22940129Speter			return -1;
23040129Speter	}
23140129Speter	return(0);
23240129Speter}
233105469Smarcel
234105469Smarcelint
235129282Speterelf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
236129282Speter    elf_lookup_fn lookup)
237109605Sjake{
238109605Sjake
239129282Speter	return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup));
240109605Sjake}
241109605Sjake
242109605Sjakeint
243129282Speterelf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
244129282Speter    int type, elf_lookup_fn lookup)
245109605Sjake{
246109605Sjake
247129282Speter	return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup));
248109605Sjake}
249109605Sjake
250109605Sjakeint
251105469Smarcelelf_cpu_load_file(linker_file_t lf __unused)
252105469Smarcel{
253105469Smarcel
254105469Smarcel	return (0);
255105469Smarcel}
256105469Smarcel
257105469Smarcelint
258105469Smarcelelf_cpu_unload_file(linker_file_t lf __unused)
259105469Smarcel{
260105469Smarcel
261105469Smarcel	return (0);
262105469Smarcel}
263