elf64_machdep.c revision 120422
1185377Ssam/*-
2187831Ssam * Copyright 1996-1998 John D. Polstra.
3185377Ssam * All rights reserved.
4185377Ssam *
5185377Ssam * Redistribution and use in source and binary forms, with or without
6185377Ssam * modification, are permitted provided that the following conditions
7185377Ssam * are met:
8185377Ssam * 1. Redistributions of source code must retain the above copyright
9185377Ssam *    notice, this list of conditions and the following disclaimer.
10185377Ssam * 2. Redistributions in binary form must reproduce the above copyright
11185377Ssam *    notice, this list of conditions and the following disclaimer in the
12185377Ssam *    documentation and/or other materials provided with the distribution.
13185377Ssam *
14185377Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15185377Ssam * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16185377Ssam * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17185907Ssam * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18185377Ssam * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19185377Ssam * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20185377Ssam * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21185377Ssam * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22185377Ssam * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23185377Ssam * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24185377Ssam *
25185377Ssam * $FreeBSD: head/sys/powerpc/powerpc/elf_machdep.c 120422 2003-09-25 01:10:26Z peter $
26185377Ssam */
27185377Ssam
28185377Ssam#include <sys/param.h>
29185377Ssam#include <sys/kernel.h>
30185377Ssam#include <sys/systm.h>
31185377Ssam#include <sys/exec.h>
32185377Ssam#include <sys/imgact.h>
33185377Ssam#include <sys/malloc.h>
34185377Ssam#include <sys/proc.h>
35185377Ssam#include <sys/namei.h>
36185377Ssam#include <sys/fcntl.h>
37185377Ssam#include <sys/sysent.h>
38185377Ssam#include <sys/imgact_elf.h>
39185377Ssam#include <sys/syscall.h>
40185377Ssam#include <sys/signalvar.h>
41185377Ssam#include <sys/vnode.h>
42185377Ssam#include <sys/linker.h>
43185377Ssam
44185377Ssam#include <vm/vm.h>
45185377Ssam#include <vm/vm_param.h>
46185377Ssam
47185377Ssam#include <machine/elf.h>
48185377Ssam#include <machine/md_var.h>
49185377Ssam
50185377Ssamstruct sysentvec elf32_freebsd_sysvec = {
51185377Ssam	SYS_MAXSYSCALL,
52185377Ssam	sysent,
53185377Ssam	0,
54185377Ssam	0,
55185377Ssam	NULL,
56185377Ssam	0,
57185377Ssam	NULL,
58185377Ssam	NULL,
59185377Ssam	__elfN(freebsd_fixup),
60185377Ssam	sendsig,
61185377Ssam	sigcode,
62185377Ssam	&szsigcode,
63185377Ssam	NULL,
64185377Ssam	"FreeBSD ELF32",
65185377Ssam	__elfN(coredump),
66185377Ssam	NULL,
67185377Ssam	MINSIGSTKSZ,
68185377Ssam	PAGE_SIZE,
69185377Ssam	VM_MIN_ADDRESS,
70185377Ssam	VM_MAXUSER_ADDRESS,
71185377Ssam	USRSTACK,
72185377Ssam	PS_STRINGS,
73185377Ssam	VM_PROT_ALL,
74185377Ssam	exec_copyout_strings,
75185377Ssam	exec_setregs,
76185380Ssam	NULL
77185380Ssam};
78185380Ssam
79185380Ssamstatic Elf32_Brandinfo freebsd_brand_info = {
80185380Ssam						ELFOSABI_FREEBSD,
81185380Ssam						EM_PPC,
82185380Ssam						"FreeBSD",
83185380Ssam						"",
84185380Ssam						"/libexec/ld-elf.so.1",
85185380Ssam						&elf32_freebsd_sysvec
86185380Ssam					  };
87185380Ssam
88185380SsamSYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
89185380Ssam	(sysinit_cfunc_t) elf32_insert_brand_entry,
90185380Ssam	&freebsd_brand_info);
91185380Ssam
92185380Ssam/* Process one elf relocation with addend. */
93185380Ssamstatic int
94185380Ssamelf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
95185380Ssam{
96185380Ssam	Elf_Addr relocbase = (Elf_Addr) lf->address;
97185380Ssam	Elf_Addr *where;
98185380Ssam	Elf_Addr addr;
99185380Ssam	Elf_Addr addend;
100185380Ssam	Elf_Word rtype, symidx;
101185380Ssam	const Elf_Rel *rel;
102185380Ssam	const Elf_Rela *rela;
103185380Ssam
104185380Ssam	switch (type) {
105185380Ssam	case ELF_RELOC_REL:
106185380Ssam		rel = (const Elf_Rel *)data;
107185380Ssam		where = (Elf_Addr *) (relocbase + rel->r_offset);
108185380Ssam		addend = *where;
109185377Ssam		rtype = ELF_R_TYPE(rel->r_info);
110185377Ssam		symidx = ELF_R_SYM(rel->r_info);
111185377Ssam		break;
112185377Ssam	case ELF_RELOC_RELA:
113185377Ssam		rela = (const Elf_Rela *)data;
114185377Ssam		where = (Elf_Addr *) (relocbase + rela->r_offset);
115185377Ssam		addend = rela->r_addend;
116185377Ssam		rtype = ELF_R_TYPE(rela->r_info);
117185377Ssam		symidx = ELF_R_SYM(rela->r_info);
118185377Ssam		break;
119185377Ssam	default:
120185377Ssam		panic("elf_reloc: unknown relocation mode %d\n", type);
121185377Ssam	}
122185377Ssam
123185380Ssam	switch (rtype) {
124185380Ssam
125185380Ssam		case R_PPC_NONE:
126185380Ssam			break;
127185377Ssam
128185377Ssam		case R_PPC_GLOB_DAT:
129185377Ssam			addr = elf_lookup(lf, symidx, 1);
130185377Ssam			if (addr == 0)
131185377Ssam				return -1;
132185377Ssam			addr += addend;
133185377Ssam			if (*where != addr)
134185377Ssam				*where = addr;
135185380Ssam			break;
136185380Ssam
137185380Ssam		case R_PPC_JMP_SLOT:
138185380Ssam			/* No point in lazy binding for kernel modules. */
139185377Ssam			addr = elf_lookup(lf, symidx, 1);
140185377Ssam			if (addr == 0)
141185377Ssam				return -1;
142185377Ssam			if (*where != addr)
143185377Ssam				*where = addr;
144185377Ssam			break;
145185377Ssam
146185377Ssam		case R_PPC_RELATIVE:
147185377Ssam			addr = relocbase + addend + *where;
148185377Ssam			if (*where != addr)
149185377Ssam				*where = addr;
150185377Ssam			break;
151185377Ssam
152185377Ssam		case R_PPC_COPY:
153185377Ssam			/*
154185377Ssam			 * There shouldn't be copy relocations in kernel
155185377Ssam			 * objects.
156185377Ssam			 */
157185377Ssam			printf("kldload: unexpected R_COPY relocation\n");
158185377Ssam			return -1;
159185377Ssam
160185377Ssam		default:
161185377Ssam			printf("kldload: unexpected relocation type %d\n",
162185377Ssam			       (int) rtype);
163185377Ssam			return -1;
164185377Ssam	}
165185377Ssam	return(0);
166185377Ssam}
167185377Ssam
168185377Ssamint
169185377Ssamelf_reloc(linker_file_t lf, const void *data, int type)
170185377Ssam{
171185377Ssam
172185377Ssam	return (elf_reloc_internal(lf, data, type, 0));
173185377Ssam}
174185377Ssam
175185377Ssamint
176185377Ssamelf_reloc_local(linker_file_t lf, const void *data, int type)
177185377Ssam{
178185377Ssam
179185377Ssam	return (elf_reloc_internal(lf, data, type, 1));
180185377Ssam}
181185377Ssam
182185377Ssamint
183185377Ssamelf_cpu_load_file(linker_file_t lf __unused)
184185377Ssam{
185185377Ssam
186185377Ssam	return (0);
187185377Ssam}
188185377Ssam
189185377Ssamint
190185377Ssamelf_cpu_unload_file(linker_file_t lf __unused)
191185377Ssam{
192185377Ssam
193185377Ssam	return (0);
194185377Ssam}
195185377Ssam