elf_machdep.c revision 129282
118334Speter/*-
218334Speter * Copyright 1996-1998 John D. Polstra.
3132718Skan * All rights reserved.
4169689Skan *
5132718Skan * Redistribution and use in source and binary forms, with or without
618334Speter * modification, are permitted provided that the following conditions
7132718Skan * are met:
818334Speter * 1. Redistributions of source code must retain the above copyright
918334Speter *    notice, this list of conditions and the following disclaimer.
1018334Speter * 2. Redistributions in binary form must reproduce the above copyright
1118334Speter *    notice, this list of conditions and the following disclaimer in the
12132718Skan *    documentation and/or other materials provided with the distribution.
1318334Speter *
1418334Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1518334Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1618334Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1718334Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18132718Skan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19169689Skan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20169689Skan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2118334Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2218334Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2350397Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24132718Skan */
25132718Skan
2618334Speter#include <sys/cdefs.h>
2718334Speter__FBSDID("$FreeBSD: head/sys/arm/arm/elf_machdep.c 129282 2004-05-16 20:00:28Z peter $");
2890075Sobrien
2950397Sobrien#include <sys/param.h>
3090075Sobrien#include <sys/kernel.h>
3190075Sobrien#include <sys/systm.h>
32117395Skan#include <sys/exec.h>
33132718Skan#include <sys/imgact.h>
3418334Speter#include <sys/linker.h>
35169689Skan#include <sys/sysent.h>
3618334Speter#include <sys/imgact_elf.h>
3790075Sobrien#include <sys/syscall.h>
3890075Sobrien#include <sys/signalvar.h>
3990075Sobrien#include <sys/vnode.h>
40132718Skan
41132718Skan#include <vm/vm.h>
4218334Speter#include <vm/pmap.h>
4390075Sobrien#include <vm/vm_param.h>
4418334Speter
45132718Skan#include <machine/elf.h>
46132718Skan#include <machine/md_var.h>
47132718Skan
48132718Skanstruct sysentvec elf32_freebsd_sysvec = {
49132718Skan	SYS_MAXSYSCALL,
50132718Skan	sysent,
51132718Skan	0,
52132718Skan	0,
53132718Skan	NULL,
54132718Skan	0,
5552284Sobrien	NULL,
56132718Skan	NULL,
57132718Skan	__elfN(freebsd_fixup),
58132718Skan	sendsig,
59132718Skan	NULL,
60132718Skan	NULL,
61132718Skan	NULL,
62132718Skan	"FreeBSD ELF32",
63132718Skan	__elfN(coredump),
64132718Skan	NULL,
65132718Skan	MINSIGSTKSZ,
66169689Skan	PAGE_SIZE,
67132718Skan	VM_MIN_ADDRESS,
68132718Skan	VM_MAXUSER_ADDRESS,
69132718Skan	USRSTACK,
70132718Skan	PS_STRINGS,
71132718Skan	VM_PROT_ALL,
72132718Skan	exec_copyout_strings,
73132718Skan	exec_setregs,
74132718Skan	NULL
75132718Skan};
76132718Skan
77132718Skanstatic Elf32_Brandinfo freebsd_brand_info = {
78132718Skan						ELFOSABI_FREEBSD,
7918334Speter						EM_ARM,
80132718Skan						"FreeBSD",
81132718Skan						NULL,
82132718Skan						"/libexec/ld-elf.so.1",
83132718Skan						&elf32_freebsd_sysvec,
84169689Skan						NULL,
85132718Skan					  };
86132718Skan
87132718SkanSYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
8818334Speter	(sysinit_cfunc_t) elf32_insert_brand_entry,
89169689Skan	&freebsd_brand_info);
90169689Skan
91132718Skanstatic Elf32_Brandinfo freebsd_brand_oinfo = {
9250397Sobrien						ELFOSABI_FREEBSD,
9318334Speter						EM_ARM,
94132718Skan						"FreeBSD",
9518334Speter						NULL,
9690075Sobrien						"/usr/libexec/ld-elf.so.1",
9790075Sobrien						&elf32_freebsd_sysvec,
9890075Sobrien						NULL,
9990075Sobrien					  };
100132718Skan
101132718SkanSYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
10218334Speter	(sysinit_cfunc_t) elf32_insert_brand_entry,
10318334Speter	&freebsd_brand_oinfo);
10490075Sobrien
10552284Sobrien/* Process one elf relocation with addend. */
10690075Sobrienstatic int
107132718Skanelf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
10852284Sobrien    int type, int local, elf_lookup_fn lookup)
10990075Sobrien{
11052284Sobrien	Elf_Addr *where;
11190075Sobrien	Elf_Addr addr;
11290075Sobrien	Elf_Addr addend;
11390075Sobrien	Elf_Word rtype, symidx;
11490075Sobrien	const Elf_Rel *rel;
11590075Sobrien	const Elf_Rela *rela;
11690075Sobrien
117169689Skan	switch (type) {
118169689Skan	case ELF_RELOC_REL:
119169689Skan		rel = (const Elf_Rel *)data;
120169689Skan		where = (Elf_Addr *) (relocbase + rel->r_offset);
12190075Sobrien		addend = *where;
12290075Sobrien		rtype = ELF_R_TYPE(rel->r_info);
12390075Sobrien		symidx = ELF_R_SYM(rel->r_info);
12490075Sobrien		break;
125169689Skan	case ELF_RELOC_RELA:
12690075Sobrien		rela = (const Elf_Rela *)data;
12790075Sobrien		where = (Elf_Addr *) (relocbase + rela->r_offset);
12890075Sobrien		addend = rela->r_addend;
12990075Sobrien		rtype = ELF_R_TYPE(rela->r_info);
130169689Skan		symidx = ELF_R_SYM(rela->r_info);
13190075Sobrien		break;
13252284Sobrien	default:
13352284Sobrien		panic("unknown reloc type %d\n", type);
13490075Sobrien	}
13552284Sobrien
13690075Sobrien	if (local) {
137132718Skan		if (rtype == R_ARM_RELATIVE) {	/* A + B */
13890075Sobrien			addr = relocbase + addend;
13990075Sobrien			if (*where != addr)
14090075Sobrien				*where = addr;
14190075Sobrien		}
14290075Sobrien		return (0);
14390075Sobrien	}
14452284Sobrien
14590075Sobrien	switch (rtype) {
14690075Sobrien
14752284Sobrien		case R_ARM_NONE:	/* none */
14890075Sobrien			break;
149132718Skan
15090075Sobrien		case R_ARM_PC24:	/* S + A - P */
15190075Sobrien			addr = lookup(lf, symidx, 1);
15290075Sobrien			if (addr == 0)
15390075Sobrien				return -1;
15452284Sobrien			addr += addend - (Elf_Addr)where;
15590075Sobrien			if (*where != addr)
15690075Sobrien				*where = addr;
15790075Sobrien			break;
158169689Skan
15990075Sobrien		case R_ARM_COPY:	/* none */
16090075Sobrien			/*
16190075Sobrien			 * There shouldn't be copy relocations in kernel
16290075Sobrien			 * objects.
16352284Sobrien			 */
16490075Sobrien			printf("kldload: unexpected R_COPY relocation\n");
16590075Sobrien			return -1;
16690075Sobrien			break;
167132718Skan
16890075Sobrien		case R_ARM_GLOB_DAT:	/* S */
169169689Skan			addr = lookup(lf, symidx, 1);
170169689Skan			if (addr == 0)
17190075Sobrien				return -1;
172169689Skan			if (*where != addr)
173169689Skan				*where = addr;
174169689Skan			break;
175169689Skan
176169689Skan		case R_ARM_RELATIVE:
177169689Skan			break;
17890075Sobrien
17990075Sobrien		default:
18090075Sobrien			printf("kldload: unexpected relocation type %d\n",
181169689Skan			       rtype);
182169689Skan			return -1;
183169689Skan	}
184169689Skan	return(0);
185169689Skan}
18690075Sobrien
187169689Skanint
18890075Sobrienelf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
189169689Skan    elf_lookup_fn lookup)
19090075Sobrien{
19190075Sobrien
19290075Sobrien	return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup));
19390075Sobrien}
19490075Sobrien
19590075Sobrienint
196169689Skanelf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
197169689Skan    int type, elf_lookup_fn lookup)
198169689Skan{
19990075Sobrien
200169689Skan	return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup));
20190075Sobrien}
202169689Skan
20390075Sobrienint
20490075Sobrienelf_cpu_load_file(linker_file_t lf __unused)
20590075Sobrien{
20690075Sobrien
20790075Sobrien	return (0);
20890075Sobrien}
20990075Sobrien
21090075Sobrienint
211132718Skanelf_cpu_unload_file(linker_file_t lf __unused)
21290075Sobrien{
21390075Sobrien
21490075Sobrien	return (0);
21590075Sobrien}
21690075Sobrien