elf32_machdep.c revision 132282
125428Speter/*-
250477Speter * Copyright 1996-1998 John D. Polstra.
325428Speter * All rights reserved.
425428Speter *
525428Speter * Redistribution and use in source and binary forms, with or without
625428Speter * modification, are permitted provided that the following conditions
725428Speter * are met:
825428Speter * 1. Redistributions of source code must retain the above copyright
925428Speter *    notice, this list of conditions and the following disclaimer.
1025428Speter * 2. Redistributions in binary form must reproduce the above copyright
1125428Speter *    notice, this list of conditions and the following disclaimer in the
1225428Speter *    documentation and/or other materials provided with the distribution.
1325428Speter *
1425428Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1525428Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1625428Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1725428Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1825428Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1925428Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2025428Speter * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2125428Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2225428Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2325428Speter * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2425428Speter *
2525428Speter * $FreeBSD: head/sys/powerpc/powerpc/elf_machdep.c 132282 2004-07-17 07:26:32Z grehan $
2625428Speter */
2725428Speter
2825428Speter#include <sys/param.h>
2925428Speter#include <sys/kernel.h>
3025428Speter#include <sys/systm.h>
3125428Speter#include <sys/exec.h>
3225428Speter#include <sys/imgact.h>
3325428Speter#include <sys/malloc.h>
3425428Speter#include <sys/proc.h>
3525428Speter#include <sys/namei.h>
3625428Speter#include <sys/fcntl.h>
3725428Speter#include <sys/sysent.h>
3825428Speter#include <sys/imgact_elf.h>
3925428Speter#include <sys/syscall.h>
4025428Speter#include <sys/signalvar.h>
4125428Speter#include <sys/vnode.h>
4225428Speter#include <sys/linker.h>
4325428Speter
4425428Speter#include <vm/vm.h>
4525428Speter#include <vm/vm_param.h>
4625428Speter
4725428Speter#include <machine/cpu.h>
4825428Speter#include <machine/elf.h>
4925428Speter#include <machine/md_var.h>
5025428Speter
5125428Speterstruct sysentvec elf32_freebsd_sysvec = {
5225428Speter	SYS_MAXSYSCALL,
5355205Speter	sysent,
5425428Speter	0,
5525428Speter	0,
5625428Speter	NULL,
5725428Speter	0,
5825428Speter	NULL,
5925428Speter	NULL,
6025428Speter	__elfN(freebsd_fixup),
6125428Speter	sendsig,
6225428Speter	sigcode,
6325428Speter	&szsigcode,
6425428Speter	NULL,
6525428Speter	"FreeBSD ELF32",
6625428Speter	__elfN(coredump),
6725428Speter	NULL,
6825428Speter	MINSIGSTKSZ,
6925428Speter	PAGE_SIZE,
7025428Speter	VM_MIN_ADDRESS,
7125428Speter	VM_MAXUSER_ADDRESS,
7225428Speter	USRSTACK,
7325428Speter	PS_STRINGS,
7425428Speter	VM_PROT_ALL,
7525428Speter	exec_copyout_strings,
7625428Speter	exec_setregs,
7725428Speter	NULL
7825428Speter};
7925428Speter
8025428Speterstatic Elf32_Brandinfo freebsd_brand_info = {
8125428Speter						ELFOSABI_FREEBSD,
8225428Speter						EM_PPC,
8325428Speter						"FreeBSD",
8425428Speter						NULL,
8525428Speter						"/libexec/ld-elf.so.1",
8625428Speter						&elf32_freebsd_sysvec,
8725428Speter						NULL,
8825428Speter					  };
8925428Speter
9045720SpeterSYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
9145720Speter	(sysinit_cfunc_t) elf32_insert_brand_entry,
9245720Speter	&freebsd_brand_info);
9325428Speter
9425428Speterstatic Elf32_Brandinfo freebsd_brand_oinfo = {
9525428Speter						ELFOSABI_FREEBSD,
9625428Speter						EM_PPC,
9725428Speter						"FreeBSD",
9825428Speter						NULL,
9925428Speter						"/usr/libexec/ld-elf.so.1",
10025428Speter						&elf32_freebsd_sysvec,
10125428Speter						NULL,
10225428Speter					  };
10325428Speter
10425428SpeterSYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
10525428Speter	(sysinit_cfunc_t) elf32_insert_brand_entry,
10625428Speter	&freebsd_brand_oinfo);
10755205Speter
10825428Speter/* Process one elf relocation with addend. */
10925428Speterstatic int
11025428Speterelf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
11125428Speter    int type, int local, elf_lookup_fn lookup)
11225428Speter{
11353649Sjulian	Elf_Addr *where;
11425428Speter	Elf_Half *hwhere;
11525428Speter	Elf_Addr addr;
11625428Speter	Elf_Addr addend;
11725428Speter	Elf_Word rtype, symidx;
11825428Speter	const Elf_Rela *rela;
11925428Speter
12025428Speter	switch (type) {
12125428Speter	case ELF_RELOC_REL:
12225428Speter		panic("PPC only supports RELA relocations");
12325428Speter		break;
12425428Speter	case ELF_RELOC_RELA:
12525428Speter		rela = (const Elf_Rela *)data;
12625428Speter		where = (Elf_Addr *) (relocbase + rela->r_offset);
12725428Speter		hwhere = (Elf_Half *) (relocbase + rela->r_offset);
12825428Speter		addend = rela->r_addend;
12925428Speter		rtype = ELF_R_TYPE(rela->r_info);
13025428Speter		symidx = ELF_R_SYM(rela->r_info);
13125428Speter		break;
13225428Speter	default:
13344521Swpaul		panic("elf_reloc: unknown relocation mode %d\n", type);
13444521Swpaul	}
13544521Swpaul
13644542Swpaul	switch (rtype) {
13744542Swpaul
13844542Swpaul       	case R_PPC_NONE:
13944542Swpaul	       	break;
14053649Sjulian
14153649Sjulian	case R_PPC_ADDR32: /* word32 S + A */
14225428Speter       		addr = lookup(lf, symidx, 1);
14325428Speter	       	if (addr == 0)
14425428Speter	       		return -1;
14525428Speter		addr += addend;
14625428Speter	       	*where = addr;
14725428Speter	       	break;
14825428Speter
14925428Speter       	case R_PPC_ADDR16_LO: /* #lo(S) */
15025428Speter       		if (addend != 0) {
15144165Sjulian	       		addr = relocbase + addend;
15244165Sjulian		} else {
15325428Speter	      		addr = lookup(lf, symidx, 1);
15425428Speter			if (addr == 0)
15525428Speter				return -1;
15644165Sjulian		}
15744165Sjulian		*hwhere = addr & 0xffff;
15844165Sjulian		break;
15925428Speter
16025428Speter	case R_PPC_ADDR16_HA: /* #ha(S) */
16125428Speter       		if (addend != 0) {
16225428Speter	       		addr = relocbase + addend;
16325428Speter		} else {
16425428Speter	       		addr = lookup(lf, symidx, 1);
16525428Speter		       	if (addr == 0)
16625428Speter		       		return -1;
16725428Speter		}
16825428Speter	       	*hwhere = ((addr >> 16) + ((addr & 0x8000) ? 1 : 0))
16925428Speter		    & 0xffff;
17025428Speter		break;
17125428Speter
17225428Speter	case R_PPC_RELATIVE: /* word32 B + A */
17325428Speter       		*where = relocbase + addend;
17425428Speter	       	break;
17525428Speter
17625428Speter	default:
17725428Speter       		printf("kldload: unexpected relocation type %d\n",
17825428Speter	       	    (int) rtype);
17925428Speter		return -1;
18025428Speter	}
18125428Speter	return(0);
18225428Speter}
18325428Speter
18425428Speterint
18525428Speterelf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
18625428Speter    elf_lookup_fn lookup)
18725428Speter{
18825428Speter
18925428Speter	return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup));
19053649Sjulian}
19125428Speter
19225428Speterint
19325428Speterelf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
19425428Speter    int type, elf_lookup_fn lookup)
19525428Speter{
19625428Speter
19725428Speter	return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup));
19825428Speter}
19925428Speter
20025428Speterint
20125428Speterelf_cpu_load_file(linker_file_t lf __unused)
20225428Speter{
20325428Speter
20425428Speter	__syncicache(lf->address, lf->size);
20544165Sjulian	return (0);
20644165Sjulian}
20744165Sjulian
20844165Sjulianint
20944521Swpaulelf_cpu_unload_file(linker_file_t lf __unused)
21025428Speter{
21144521Swpaul
21244521Swpaul	return (0);
21325428Speter}
21444521Swpaul