elf32_machdep.c revision 100384
1/*-
2 * Copyright 1996-1998 John D. Polstra.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * $FreeBSD: head/sys/powerpc/powerpc/elf_machdep.c 100384 2002-07-20 02:56:12Z peter $
26 */
27
28#include <sys/param.h>
29#include <sys/kernel.h>
30#include <sys/systm.h>
31#include <sys/malloc.h>
32#include <sys/proc.h>
33#include <sys/namei.h>
34#include <sys/fcntl.h>
35#include <sys/sysent.h>
36#include <sys/imgact_elf.h>
37#include <sys/syscall.h>
38#include <sys/signalvar.h>
39#include <sys/vnode.h>
40#include <sys/linker.h>
41#include <machine/elf.h>
42#include <machine/md_var.h>
43
44struct sysentvec elf32_freebsd_sysvec = {
45	SYS_MAXSYSCALL,
46	sysent,
47	0,
48	0,
49	0,
50	0,
51	0,
52	0,
53	elf32_freebsd_fixup,
54	sendsig,
55	sigcode,
56	&szsigcode,
57	0,
58	"FreeBSD ELF32",
59	__elfN(coredump),
60	NULL,
61	MINSIGSTKSZ
62};
63
64static Elf32_Brandinfo freebsd_brand_info = {
65						ELFOSABI_FREEBSD,
66						EM_PPC,
67						"FreeBSD",
68						"",
69						"/usr/libexec/ld-elf.so.1",
70						&elf32_freebsd_sysvec
71					  };
72
73SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
74	(sysinit_cfunc_t) elf32_insert_brand_entry,
75	&freebsd_brand_info);
76
77/* Process one elf relocation with addend. */
78int
79elf_reloc(linker_file_t lf, const void *data, int type)
80{
81	Elf_Addr relocbase = (Elf_Addr) lf->address;
82	Elf_Addr *where;
83	Elf_Addr addr;
84	Elf_Addr addend;
85	Elf_Word rtype, symidx;
86	const Elf_Rel *rel;
87	const Elf_Rela *rela;
88
89	switch (type) {
90	case ELF_RELOC_REL:
91		rel = (const Elf_Rel *)data;
92		where = (Elf_Addr *) (relocbase + rel->r_offset);
93		addend = *where;
94		rtype = ELF_R_TYPE(rel->r_info);
95		symidx = ELF_R_SYM(rel->r_info);
96		break;
97	case ELF_RELOC_RELA:
98		rela = (const Elf_Rela *)data;
99		where = (Elf_Addr *) (relocbase + rela->r_offset);
100		addend = rela->r_addend;
101		rtype = ELF_R_TYPE(rela->r_info);
102		symidx = ELF_R_SYM(rela->r_info);
103		break;
104	default:
105		panic("elf_reloc: unknown relocation mode %d\n", type);
106	}
107
108	switch (rtype) {
109
110		case R_PPC_NONE:
111			break;
112
113		case R_PPC_GLOB_DAT:
114			addr = elf_lookup(lf, symidx, 1);
115			if (addr == 0)
116				return -1;
117			addr += addend;
118			if (*where != addr)
119				*where = addr;
120			break;
121
122		case R_PPC_JMP_SLOT:
123			/* No point in lazy binding for kernel modules. */
124			addr = elf_lookup(lf, symidx, 1);
125			if (addr == 0)
126				return -1;
127			if (*where != addr)
128				*where = addr;
129			break;
130
131		case R_PPC_RELATIVE:
132			addr = relocbase + addend + *where;
133			if (*where != addr)
134				*where = addr;
135			break;
136
137		case R_PPC_COPY:
138			/*
139			 * There shouldn't be copy relocations in kernel
140			 * objects.
141			 */
142			printf("kldload: unexpected R_COPY relocation\n");
143			return -1;
144
145		default:
146			printf("kldload: unexpected relocation type %d\n",
147			       (int) rtype);
148			return -1;
149	}
150	return(0);
151}
152