]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/amd64/amd64/elf_machdep.c
Infrastructure tweaks to allow having both an Elf32 and an Elf64 executable
[FreeBSD/FreeBSD.git] / sys / amd64 / amd64 / elf_machdep.c
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$
26  */
27
28 #include <sys/param.h>
29 #include <sys/kernel.h>
30 #include <sys/systm.h>
31 #include <sys/linker.h>
32 #include <sys/sysent.h>
33 #include <sys/imgact_elf.h>
34 #include <sys/syscall.h>
35 #include <sys/signalvar.h>
36 #include <sys/vnode.h>
37 #include <machine/elf.h>
38 #include <machine/md_var.h>
39
40 struct sysentvec elf32_freebsd_sysvec = {
41         SYS_MAXSYSCALL,
42         sysent,
43         0,
44         0,
45         0,
46         0,
47         0,
48         0,
49         elf32_freebsd_fixup,
50         sendsig,
51         sigcode,
52         &szsigcode,
53         0,
54         "FreeBSD ELF32",
55         __elfN(coredump),
56         NULL,
57         MINSIGSTKSZ
58 };
59
60 static Elf32_Brandinfo freebsd_brand_info = {
61                                                 ELFOSABI_FREEBSD,
62                                                 EM_386,
63                                                 "FreeBSD",
64                                                 "",
65                                                 "/usr/libexec/ld-elf.so.1",
66                                                 &elf32_freebsd_sysvec
67                                           };
68
69 SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
70         (sysinit_cfunc_t) elf32_insert_brand_entry,
71         &freebsd_brand_info);
72
73 /* Process one elf relocation with addend. */
74 int
75 elf_reloc(linker_file_t lf, const void *data, int type)
76 {
77         Elf_Addr relocbase = (Elf_Addr) lf->address;
78         Elf_Addr *where;
79         Elf_Addr addr;
80         Elf_Addr addend;
81         Elf_Word rtype, symidx;
82         const Elf_Rel *rel;
83         const Elf_Rela *rela;
84
85         switch (type) {
86         case ELF_RELOC_REL:
87                 rel = (const Elf_Rel *)data;
88                 where = (Elf_Addr *) (relocbase + rel->r_offset);
89                 addend = *where;
90                 rtype = ELF_R_TYPE(rel->r_info);
91                 symidx = ELF_R_SYM(rel->r_info);
92                 break;
93         case ELF_RELOC_RELA:
94                 rela = (const Elf_Rela *)data;
95                 where = (Elf_Addr *) (relocbase + rela->r_offset);
96                 addend = rela->r_addend;
97                 rtype = ELF_R_TYPE(rela->r_info);
98                 symidx = ELF_R_SYM(rela->r_info);
99                 break;
100         default:
101                 panic("unknown reloc type %d\n", type);
102         }
103
104         switch (rtype) {
105
106                 case R_386_NONE:        /* none */
107                         break;
108
109                 case R_386_32:          /* S + A */
110                         addr = elf_lookup(lf, symidx, 1);
111                         if (addr == 0)
112                                 return -1;
113                         addr += addend;
114                         if (*where != addr)
115                                 *where = addr;
116                         break;
117
118                 case R_386_PC32:        /* S + A - P */
119                         addr = elf_lookup(lf, symidx, 1);
120                         if (addr == 0)
121                                 return -1;
122                         addr += addend - (Elf_Addr)where;
123                         if (*where != addr)
124                                 *where = addr;
125                         break;
126
127                 case R_386_COPY:        /* none */
128                         /*
129                          * There shouldn't be copy relocations in kernel
130                          * objects.
131                          */
132                         printf("kldload: unexpected R_COPY relocation\n");
133                         return -1;
134                         break;
135
136                 case R_386_GLOB_DAT:    /* S */
137                         addr = elf_lookup(lf, symidx, 1);
138                         if (addr == 0)
139                                 return -1;
140                         if (*where != addr)
141                                 *where = addr;
142                         break;
143
144                 case R_386_RELATIVE:    /* B + A */
145                         addr = relocbase + addend;
146                         if (*where != addr)
147                                 *where = addr;
148                         break;
149
150                 default:
151                         printf("kldload: unexpected relocation type %d\n",
152                                rtype);
153                         return -1;
154         }
155         return(0);
156 }