xref: /freebsd/sys/amd64/amd64/elf_machdep.c (revision f1d19042)
1033f58dfSPeter Wemm /*-
2033f58dfSPeter Wemm  * Copyright 1996-1998 John D. Polstra.
3033f58dfSPeter Wemm  * All rights reserved.
4033f58dfSPeter Wemm  *
5033f58dfSPeter Wemm  * Redistribution and use in source and binary forms, with or without
6033f58dfSPeter Wemm  * modification, are permitted provided that the following conditions
7033f58dfSPeter Wemm  * are met:
8033f58dfSPeter Wemm  * 1. Redistributions of source code must retain the above copyright
9033f58dfSPeter Wemm  *    notice, this list of conditions and the following disclaimer.
10033f58dfSPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
11033f58dfSPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
12033f58dfSPeter Wemm  *    documentation and/or other materials provided with the distribution.
13033f58dfSPeter Wemm  *
14033f58dfSPeter Wemm  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15033f58dfSPeter Wemm  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16033f58dfSPeter Wemm  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17033f58dfSPeter Wemm  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18033f58dfSPeter Wemm  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19033f58dfSPeter Wemm  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20033f58dfSPeter Wemm  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21033f58dfSPeter Wemm  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22033f58dfSPeter Wemm  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23033f58dfSPeter Wemm  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24033f58dfSPeter Wemm  *
25f1d19042SArchie Cobbs  *      $Id: elf_machdep.c,v 1.3 1998/10/16 03:54:59 peter Exp $
26033f58dfSPeter Wemm  */
27033f58dfSPeter Wemm 
28033f58dfSPeter Wemm #include <sys/param.h>
29033f58dfSPeter Wemm #include <sys/kernel.h>
30033f58dfSPeter Wemm #include <sys/systm.h>
31033f58dfSPeter Wemm #include <sys/malloc.h>
32033f58dfSPeter Wemm #include <sys/proc.h>
33033f58dfSPeter Wemm #include <sys/namei.h>
34033f58dfSPeter Wemm #include <sys/fcntl.h>
35033f58dfSPeter Wemm #include <sys/vnode.h>
36033f58dfSPeter Wemm #include <sys/linker.h>
37033f58dfSPeter Wemm #include <machine/elf.h>
38033f58dfSPeter Wemm 
39bde362f5SPeter Wemm /* Process one elf relocation with addend. */
40033f58dfSPeter Wemm int
41aa855a59SPeter Wemm elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
42033f58dfSPeter Wemm {
43033f58dfSPeter Wemm 	Elf_Addr relocbase = (Elf_Addr) lf->address;
44aa855a59SPeter Wemm 	Elf_Addr *where;
45f1d19042SArchie Cobbs 	Elf_Addr addr;
46aa855a59SPeter Wemm 	Elf_Addr addend;
47aa855a59SPeter Wemm 	Elf_Word rtype;
48aa855a59SPeter Wemm 	const Elf_Rel *rel;
49aa855a59SPeter Wemm 	const Elf_Rela *rela;
50033f58dfSPeter Wemm 
51aa855a59SPeter Wemm 	switch (type) {
52aa855a59SPeter Wemm 	case ELF_RELOC_REL:
53aa855a59SPeter Wemm 		rel = (Elf_Rel *)data;
54aa855a59SPeter Wemm 		where = (Elf_Addr *) (relocbase + rel->r_offset);
55aa855a59SPeter Wemm 		addend = *where;
56aa855a59SPeter Wemm 		rtype = ELF_R_TYPE(rel->r_info);
57aa855a59SPeter Wemm 		break;
58aa855a59SPeter Wemm 	case ELF_RELOC_RELA:
59aa855a59SPeter Wemm 		rela = (Elf_Rela *)data;
60aa855a59SPeter Wemm 		where = (Elf_Addr *) (relocbase + rela->r_offset);
61aa855a59SPeter Wemm 		addend = rela->r_addend;
62aa855a59SPeter Wemm 		rtype = ELF_R_TYPE(rela->r_info);
63aa855a59SPeter Wemm 		break;
64aa855a59SPeter Wemm 	default:
65aa855a59SPeter Wemm 		panic("unknown reloc type %d\n", type);
66aa855a59SPeter Wemm 	}
67033f58dfSPeter Wemm 
68aa855a59SPeter Wemm 	switch (rtype) {
69aa855a59SPeter Wemm 
70aa855a59SPeter Wemm 		case R_386_NONE:	/* none */
71033f58dfSPeter Wemm 			break;
72033f58dfSPeter Wemm 
73aa855a59SPeter Wemm 		case R_386_32:		/* S + A */
74aa855a59SPeter Wemm 			if (sym == NULL)
75aa855a59SPeter Wemm 				return -1;
76033f58dfSPeter Wemm 			addr = (Elf_Addr)linker_file_lookup_symbol(lf, sym, 1);
77033f58dfSPeter Wemm 			if (addr == NULL)
78033f58dfSPeter Wemm 				return -1;
79aa855a59SPeter Wemm 			addr += addend;
80033f58dfSPeter Wemm 			if (*where != addr)
81033f58dfSPeter Wemm 				*where = addr;
82033f58dfSPeter Wemm 			break;
83033f58dfSPeter Wemm 
84aa855a59SPeter Wemm 		case R_386_PC32:	/* S + A - P */
85aa855a59SPeter Wemm 			if (sym == NULL)
86aa855a59SPeter Wemm 				return -1;
87033f58dfSPeter Wemm 			addr = (Elf_Addr)linker_file_lookup_symbol(lf, sym, 1);
88033f58dfSPeter Wemm 			if (addr == NULL)
89033f58dfSPeter Wemm 				return -1;
90aa855a59SPeter Wemm 			addr += addend - (Elf_Addr)where;
91033f58dfSPeter Wemm 			if (*where != addr)
92033f58dfSPeter Wemm 				*where = addr;
93033f58dfSPeter Wemm 			break;
94033f58dfSPeter Wemm 
95aa855a59SPeter Wemm 		case R_386_COPY:	/* none */
96033f58dfSPeter Wemm 			/*
97033f58dfSPeter Wemm 			 * There shouldn't be copy relocations in kernel
98033f58dfSPeter Wemm 			 * objects.
99033f58dfSPeter Wemm 			 */
100033f58dfSPeter Wemm 			printf("kldload: unexpected R_COPY relocation\n");
101033f58dfSPeter Wemm 			return -1;
102033f58dfSPeter Wemm 			break;
103033f58dfSPeter Wemm 
104aa855a59SPeter Wemm 		case R_386_GLOB_DAT:	/* S */
105aa855a59SPeter Wemm 			if (sym == NULL)
106aa855a59SPeter Wemm 				return -1;
107033f58dfSPeter Wemm 			addr = (Elf_Addr)linker_file_lookup_symbol(lf, sym, 1);
108033f58dfSPeter Wemm 			if (addr == NULL)
109033f58dfSPeter Wemm 				return -1;
110033f58dfSPeter Wemm 			if (*where != addr)
111033f58dfSPeter Wemm 				*where = addr;
112033f58dfSPeter Wemm 			break;
113033f58dfSPeter Wemm 
114aa855a59SPeter Wemm 		case R_386_RELATIVE:	/* B + A */
115aa855a59SPeter Wemm 			addr = relocbase + addend;
116aa855a59SPeter Wemm 			if (*where != addr)
117aa855a59SPeter Wemm 				*where = addr;
118033f58dfSPeter Wemm 			break;
119033f58dfSPeter Wemm 
120033f58dfSPeter Wemm 		default:
121033f58dfSPeter Wemm 			printf("kldload: unexpected relocation type %d\n",
122aa855a59SPeter Wemm 			       rtype);
123033f58dfSPeter Wemm 			return -1;
124033f58dfSPeter Wemm 	}
125033f58dfSPeter Wemm 	return(0);
126033f58dfSPeter Wemm }
127