| @@ -1,816 +1,816 @@ | | | @@ -1,816 +1,816 @@ |
1 | /* $NetBSD: loadfile_elf32.c,v 1.52 2017/12/21 14:28:39 maxv Exp $ */ | | 1 | /* $NetBSD: loadfile_elf32.c,v 1.53 2018/08/23 17:35:42 jmcneill Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1997, 2008, 2017 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1997, 2008, 2017 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | | 8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, |
9 | * NASA Ames Research Center, by Christos Zoulas, and by Maxime Villard. | | 9 | * NASA Ames Research Center, by Christos Zoulas, and by Maxime Villard. |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
15 | * notice, this list of conditions and the following disclaimer. | | 15 | * notice, this list of conditions and the following disclaimer. |
16 | * 2. Redistributions in binary form must reproduce the above copyright | | 16 | * 2. Redistributions in binary form must reproduce the above copyright |
17 | * notice, this list of conditions and the following disclaimer in the | | 17 | * notice, this list of conditions and the following disclaimer in the |
18 | * documentation and/or other materials provided with the distribution. | | 18 | * documentation and/or other materials provided with the distribution. |
19 | * | | 19 | * |
20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
30 | * POSSIBILITY OF SUCH DAMAGE. | | 30 | * POSSIBILITY OF SUCH DAMAGE. |
31 | */ | | 31 | */ |
32 | | | 32 | |
33 | /* If not included by exec_elf64.c, ELFSIZE won't be defined. */ | | 33 | /* If not included by exec_elf64.c, ELFSIZE won't be defined. */ |
34 | #ifndef ELFSIZE | | 34 | #ifndef ELFSIZE |
35 | #define ELFSIZE 32 | | 35 | #define ELFSIZE 32 |
36 | #endif | | 36 | #endif |
37 | | | 37 | |
38 | #ifdef _STANDALONE | | 38 | #ifdef _STANDALONE |
39 | #include <lib/libsa/stand.h> | | 39 | #include <lib/libsa/stand.h> |
40 | #include <lib/libkern/libkern.h> | | 40 | #include <lib/libkern/libkern.h> |
41 | #else | | 41 | #else |
42 | #include <stdio.h> | | 42 | #include <stdio.h> |
43 | #include <string.h> | | 43 | #include <string.h> |
44 | #include <errno.h> | | 44 | #include <errno.h> |
45 | #include <stdlib.h> | | 45 | #include <stdlib.h> |
46 | #include <unistd.h> | | 46 | #include <unistd.h> |
47 | #include <fcntl.h> | | 47 | #include <fcntl.h> |
48 | #include <err.h> | | 48 | #include <err.h> |
49 | #endif | | 49 | #endif |
50 | | | 50 | |
51 | #include <sys/param.h> | | 51 | #include <sys/param.h> |
52 | #include <sys/exec.h> | | 52 | #include <sys/exec.h> |
53 | | | 53 | |
54 | #include "loadfile.h" | | 54 | #include "loadfile.h" |
55 | | | 55 | |
56 | #if ((ELFSIZE == 32) && defined(BOOT_ELF32)) || \ | | 56 | #if ((ELFSIZE == 32) && defined(BOOT_ELF32)) || \ |
57 | ((ELFSIZE == 64) && defined(BOOT_ELF64)) | | 57 | ((ELFSIZE == 64) && defined(BOOT_ELF64)) |
58 | | | 58 | |
59 | #define ELFROUND (ELFSIZE / 8) | | 59 | #define ELFROUND (ELFSIZE / 8) |
60 | | | 60 | |
61 | #ifndef _STANDALONE | | 61 | #ifndef _STANDALONE |
62 | #include "byteorder.h" | | 62 | #include "byteorder.h" |
63 | | | 63 | |
64 | /* | | 64 | /* |
65 | * Byte swapping may be necessary in the non-_STANDLONE case because | | 65 | * Byte swapping may be necessary in the non-_STANDLONE case because |
66 | * we may be built with a host compiler. | | 66 | * we may be built with a host compiler. |
67 | */ | | 67 | */ |
68 | #define E16(f) \ | | 68 | #define E16(f) \ |
69 | f = (bo == ELFDATA2LSB) ? sa_htole16(f) : sa_htobe16(f) | | 69 | f = (bo == ELFDATA2LSB) ? sa_htole16(f) : sa_htobe16(f) |
70 | #define E32(f) \ | | 70 | #define E32(f) \ |
71 | f = (bo == ELFDATA2LSB) ? sa_htole32(f) : sa_htobe32(f) | | 71 | f = (bo == ELFDATA2LSB) ? sa_htole32(f) : sa_htobe32(f) |
72 | #define E64(f) \ | | 72 | #define E64(f) \ |
73 | f = (bo == ELFDATA2LSB) ? sa_htole64(f) : sa_htobe64(f) | | 73 | f = (bo == ELFDATA2LSB) ? sa_htole64(f) : sa_htobe64(f) |
74 | | | 74 | |
75 | #define I16(f) \ | | 75 | #define I16(f) \ |
76 | f = (bo == ELFDATA2LSB) ? sa_le16toh(f) : sa_be16toh(f) | | 76 | f = (bo == ELFDATA2LSB) ? sa_le16toh(f) : sa_be16toh(f) |
77 | #define I32(f) \ | | 77 | #define I32(f) \ |
78 | f = (bo == ELFDATA2LSB) ? sa_le32toh(f) : sa_be32toh(f) | | 78 | f = (bo == ELFDATA2LSB) ? sa_le32toh(f) : sa_be32toh(f) |
79 | #define I64(f) \ | | 79 | #define I64(f) \ |
80 | f = (bo == ELFDATA2LSB) ? sa_le64toh(f) : sa_be64toh(f) | | 80 | f = (bo == ELFDATA2LSB) ? sa_le64toh(f) : sa_be64toh(f) |
81 | | | 81 | |
82 | static void | | 82 | static void |
83 | internalize_ehdr(Elf_Byte bo, Elf_Ehdr *ehdr) | | 83 | internalize_ehdr(Elf_Byte bo, Elf_Ehdr *ehdr) |
84 | { | | 84 | { |
85 | | | 85 | |
86 | #if ELFSIZE == 32 | | 86 | #if ELFSIZE == 32 |
87 | I16(ehdr->e_type); | | 87 | I16(ehdr->e_type); |
88 | I16(ehdr->e_machine); | | 88 | I16(ehdr->e_machine); |
89 | I32(ehdr->e_version); | | 89 | I32(ehdr->e_version); |
90 | I32(ehdr->e_entry); | | 90 | I32(ehdr->e_entry); |
91 | I32(ehdr->e_phoff); | | 91 | I32(ehdr->e_phoff); |
92 | I32(ehdr->e_shoff); | | 92 | I32(ehdr->e_shoff); |
93 | I32(ehdr->e_flags); | | 93 | I32(ehdr->e_flags); |
94 | I16(ehdr->e_ehsize); | | 94 | I16(ehdr->e_ehsize); |
95 | I16(ehdr->e_phentsize); | | 95 | I16(ehdr->e_phentsize); |
96 | I16(ehdr->e_phnum); | | 96 | I16(ehdr->e_phnum); |
97 | I16(ehdr->e_shentsize); | | 97 | I16(ehdr->e_shentsize); |
98 | I16(ehdr->e_shnum); | | 98 | I16(ehdr->e_shnum); |
99 | I16(ehdr->e_shstrndx); | | 99 | I16(ehdr->e_shstrndx); |
100 | #elif ELFSIZE == 64 | | 100 | #elif ELFSIZE == 64 |
101 | I16(ehdr->e_type); | | 101 | I16(ehdr->e_type); |
102 | I16(ehdr->e_machine); | | 102 | I16(ehdr->e_machine); |
103 | I32(ehdr->e_version); | | 103 | I32(ehdr->e_version); |
104 | I64(ehdr->e_entry); | | 104 | I64(ehdr->e_entry); |
105 | I64(ehdr->e_phoff); | | 105 | I64(ehdr->e_phoff); |
106 | I64(ehdr->e_shoff); | | 106 | I64(ehdr->e_shoff); |
107 | I32(ehdr->e_flags); | | 107 | I32(ehdr->e_flags); |
108 | I16(ehdr->e_ehsize); | | 108 | I16(ehdr->e_ehsize); |
109 | I16(ehdr->e_phentsize); | | 109 | I16(ehdr->e_phentsize); |
110 | I16(ehdr->e_phnum); | | 110 | I16(ehdr->e_phnum); |
111 | I16(ehdr->e_shentsize); | | 111 | I16(ehdr->e_shentsize); |
112 | I16(ehdr->e_shnum); | | 112 | I16(ehdr->e_shnum); |
113 | I16(ehdr->e_shstrndx); | | 113 | I16(ehdr->e_shstrndx); |
114 | #else | | 114 | #else |
115 | #error ELFSIZE is not 32 or 64 | | 115 | #error ELFSIZE is not 32 or 64 |
116 | #endif | | 116 | #endif |
117 | } | | 117 | } |
118 | | | 118 | |
119 | static void | | 119 | static void |
120 | externalize_ehdr(Elf_Byte bo, Elf_Ehdr *ehdr) | | 120 | externalize_ehdr(Elf_Byte bo, Elf_Ehdr *ehdr) |
121 | { | | 121 | { |
122 | | | 122 | |
123 | #if ELFSIZE == 32 | | 123 | #if ELFSIZE == 32 |
124 | E16(ehdr->e_type); | | 124 | E16(ehdr->e_type); |
125 | E16(ehdr->e_machine); | | 125 | E16(ehdr->e_machine); |
126 | E32(ehdr->e_version); | | 126 | E32(ehdr->e_version); |
127 | E32(ehdr->e_entry); | | 127 | E32(ehdr->e_entry); |
128 | E32(ehdr->e_phoff); | | 128 | E32(ehdr->e_phoff); |
129 | E32(ehdr->e_shoff); | | 129 | E32(ehdr->e_shoff); |
130 | E32(ehdr->e_flags); | | 130 | E32(ehdr->e_flags); |
131 | E16(ehdr->e_ehsize); | | 131 | E16(ehdr->e_ehsize); |
132 | E16(ehdr->e_phentsize); | | 132 | E16(ehdr->e_phentsize); |
133 | E16(ehdr->e_phnum); | | 133 | E16(ehdr->e_phnum); |
134 | E16(ehdr->e_shentsize); | | 134 | E16(ehdr->e_shentsize); |
135 | E16(ehdr->e_shnum); | | 135 | E16(ehdr->e_shnum); |
136 | E16(ehdr->e_shstrndx); | | 136 | E16(ehdr->e_shstrndx); |
137 | #elif ELFSIZE == 64 | | 137 | #elif ELFSIZE == 64 |
138 | E16(ehdr->e_type); | | 138 | E16(ehdr->e_type); |
139 | E16(ehdr->e_machine); | | 139 | E16(ehdr->e_machine); |
140 | E32(ehdr->e_version); | | 140 | E32(ehdr->e_version); |
141 | E64(ehdr->e_entry); | | 141 | E64(ehdr->e_entry); |
142 | E64(ehdr->e_phoff); | | 142 | E64(ehdr->e_phoff); |
143 | E64(ehdr->e_shoff); | | 143 | E64(ehdr->e_shoff); |
144 | E32(ehdr->e_flags); | | 144 | E32(ehdr->e_flags); |
145 | E16(ehdr->e_ehsize); | | 145 | E16(ehdr->e_ehsize); |
146 | E16(ehdr->e_phentsize); | | 146 | E16(ehdr->e_phentsize); |
147 | E16(ehdr->e_phnum); | | 147 | E16(ehdr->e_phnum); |
148 | E16(ehdr->e_shentsize); | | 148 | E16(ehdr->e_shentsize); |
149 | E16(ehdr->e_shnum); | | 149 | E16(ehdr->e_shnum); |
150 | E16(ehdr->e_shstrndx); | | 150 | E16(ehdr->e_shstrndx); |
151 | #else | | 151 | #else |
152 | #error ELFSIZE is not 32 or 64 | | 152 | #error ELFSIZE is not 32 or 64 |
153 | #endif | | 153 | #endif |
154 | } | | 154 | } |
155 | | | 155 | |
156 | static void | | 156 | static void |
157 | internalize_phdr(Elf_Byte bo, Elf_Phdr *phdr) | | 157 | internalize_phdr(Elf_Byte bo, Elf_Phdr *phdr) |
158 | { | | 158 | { |
159 | | | 159 | |
160 | #if ELFSIZE == 32 | | 160 | #if ELFSIZE == 32 |
161 | I32(phdr->p_type); | | 161 | I32(phdr->p_type); |
162 | I32(phdr->p_offset); | | 162 | I32(phdr->p_offset); |
163 | I32(phdr->p_vaddr); | | 163 | I32(phdr->p_vaddr); |
164 | I32(phdr->p_paddr); | | 164 | I32(phdr->p_paddr); |
165 | I32(phdr->p_filesz); | | 165 | I32(phdr->p_filesz); |
166 | I32(phdr->p_memsz); | | 166 | I32(phdr->p_memsz); |
167 | I32(phdr->p_flags); | | 167 | I32(phdr->p_flags); |
168 | I32(phdr->p_align); | | 168 | I32(phdr->p_align); |
169 | #elif ELFSIZE == 64 | | 169 | #elif ELFSIZE == 64 |
170 | I32(phdr->p_type); | | 170 | I32(phdr->p_type); |
171 | I32(phdr->p_offset); | | 171 | I32(phdr->p_offset); |
172 | I64(phdr->p_vaddr); | | 172 | I64(phdr->p_vaddr); |
173 | I64(phdr->p_paddr); | | 173 | I64(phdr->p_paddr); |
174 | I64(phdr->p_filesz); | | 174 | I64(phdr->p_filesz); |
175 | I64(phdr->p_memsz); | | 175 | I64(phdr->p_memsz); |
176 | I64(phdr->p_flags); | | 176 | I64(phdr->p_flags); |
177 | I64(phdr->p_align); | | 177 | I64(phdr->p_align); |
178 | #else | | 178 | #else |
179 | #error ELFSIZE is not 32 or 64 | | 179 | #error ELFSIZE is not 32 or 64 |
180 | #endif | | 180 | #endif |
181 | } | | 181 | } |
182 | | | 182 | |
183 | static void | | 183 | static void |
184 | internalize_shdr(Elf_Byte bo, Elf_Shdr *shdr) | | 184 | internalize_shdr(Elf_Byte bo, Elf_Shdr *shdr) |
185 | { | | 185 | { |
186 | | | 186 | |
187 | #if ELFSIZE == 32 | | 187 | #if ELFSIZE == 32 |
188 | I32(shdr->sh_name); | | 188 | I32(shdr->sh_name); |
189 | I32(shdr->sh_type); | | 189 | I32(shdr->sh_type); |
190 | I32(shdr->sh_flags); | | 190 | I32(shdr->sh_flags); |
191 | I32(shdr->sh_addr); | | 191 | I32(shdr->sh_addr); |
192 | I32(shdr->sh_offset); | | 192 | I32(shdr->sh_offset); |
193 | I32(shdr->sh_size); | | 193 | I32(shdr->sh_size); |
194 | I32(shdr->sh_link); | | 194 | I32(shdr->sh_link); |
195 | I32(shdr->sh_info); | | 195 | I32(shdr->sh_info); |
196 | I32(shdr->sh_addralign); | | 196 | I32(shdr->sh_addralign); |
197 | I32(shdr->sh_entsize); | | 197 | I32(shdr->sh_entsize); |
198 | #elif ELFSIZE == 64 | | 198 | #elif ELFSIZE == 64 |
199 | I32(shdr->sh_name); | | 199 | I32(shdr->sh_name); |
200 | I32(shdr->sh_type); | | 200 | I32(shdr->sh_type); |
201 | I64(shdr->sh_flags); | | 201 | I64(shdr->sh_flags); |
202 | I64(shdr->sh_addr); | | 202 | I64(shdr->sh_addr); |
203 | I64(shdr->sh_offset); | | 203 | I64(shdr->sh_offset); |
204 | I64(shdr->sh_size); | | 204 | I64(shdr->sh_size); |
205 | I32(shdr->sh_link); | | 205 | I32(shdr->sh_link); |
206 | I32(shdr->sh_info); | | 206 | I32(shdr->sh_info); |
207 | I64(shdr->sh_addralign); | | 207 | I64(shdr->sh_addralign); |
208 | I64(shdr->sh_entsize); | | 208 | I64(shdr->sh_entsize); |
209 | #else | | 209 | #else |
210 | #error ELFSIZE is not 32 or 64 | | 210 | #error ELFSIZE is not 32 or 64 |
211 | #endif | | 211 | #endif |
212 | } | | 212 | } |
213 | | | 213 | |
214 | static void | | 214 | static void |
215 | externalize_shdr(Elf_Byte bo, Elf_Shdr *shdr) | | 215 | externalize_shdr(Elf_Byte bo, Elf_Shdr *shdr) |
216 | { | | 216 | { |
217 | | | 217 | |
218 | #if ELFSIZE == 32 | | 218 | #if ELFSIZE == 32 |
219 | E32(shdr->sh_name); | | 219 | E32(shdr->sh_name); |
220 | E32(shdr->sh_type); | | 220 | E32(shdr->sh_type); |
221 | E32(shdr->sh_flags); | | 221 | E32(shdr->sh_flags); |
222 | E32(shdr->sh_addr); | | 222 | E32(shdr->sh_addr); |
223 | E32(shdr->sh_offset); | | 223 | E32(shdr->sh_offset); |
224 | E32(shdr->sh_size); | | 224 | E32(shdr->sh_size); |
225 | E32(shdr->sh_link); | | 225 | E32(shdr->sh_link); |
226 | E32(shdr->sh_info); | | 226 | E32(shdr->sh_info); |
227 | E32(shdr->sh_addralign); | | 227 | E32(shdr->sh_addralign); |
228 | E32(shdr->sh_entsize); | | 228 | E32(shdr->sh_entsize); |
229 | #elif ELFSIZE == 64 | | 229 | #elif ELFSIZE == 64 |
230 | E32(shdr->sh_name); | | 230 | E32(shdr->sh_name); |
231 | E32(shdr->sh_type); | | 231 | E32(shdr->sh_type); |
232 | E64(shdr->sh_flags); | | 232 | E64(shdr->sh_flags); |
233 | E64(shdr->sh_addr); | | 233 | E64(shdr->sh_addr); |
234 | E64(shdr->sh_offset); | | 234 | E64(shdr->sh_offset); |
235 | E64(shdr->sh_size); | | 235 | E64(shdr->sh_size); |
236 | E32(shdr->sh_link); | | 236 | E32(shdr->sh_link); |
237 | E32(shdr->sh_info); | | 237 | E32(shdr->sh_info); |
238 | E64(shdr->sh_addralign); | | 238 | E64(shdr->sh_addralign); |
239 | E64(shdr->sh_entsize); | | 239 | E64(shdr->sh_entsize); |
240 | #else | | 240 | #else |
241 | #error ELFSIZE is not 32 or 64 | | 241 | #error ELFSIZE is not 32 or 64 |
242 | #endif | | 242 | #endif |
243 | } | | 243 | } |
244 | #else /* _STANDALONE */ | | 244 | #else /* _STANDALONE */ |
245 | /* | | 245 | /* |
246 | * Byte swapping is never necessary in the _STANDALONE case because | | 246 | * Byte swapping is never necessary in the _STANDALONE case because |
247 | * we are being built with the target compiler. | | 247 | * we are being built with the target compiler. |
248 | */ | | 248 | */ |
249 | #define internalize_ehdr(bo, ehdr) /* nothing */ | | 249 | #define internalize_ehdr(bo, ehdr) /* nothing */ |
250 | #define externalize_ehdr(bo, ehdr) /* nothing */ | | 250 | #define externalize_ehdr(bo, ehdr) /* nothing */ |
251 | | | 251 | |
252 | #define internalize_phdr(bo, phdr) /* nothing */ | | 252 | #define internalize_phdr(bo, phdr) /* nothing */ |
253 | | | 253 | |
254 | #define internalize_shdr(bo, shdr) /* nothing */ | | 254 | #define internalize_shdr(bo, shdr) /* nothing */ |
255 | #define externalize_shdr(bo, shdr) /* nothing */ | | 255 | #define externalize_shdr(bo, shdr) /* nothing */ |
256 | #endif /* _STANDALONE */ | | 256 | #endif /* _STANDALONE */ |
257 | | | 257 | |
258 | #define IS_TEXT(p) (p.p_flags & PF_X) | | 258 | #define IS_TEXT(p) (p.p_flags & PF_X) |
259 | #define IS_DATA(p) (p.p_flags & PF_W) | | 259 | #define IS_DATA(p) ((p.p_flags & PF_X) == 0) |
260 | #define IS_BSS(p) (p.p_filesz < p.p_memsz) | | 260 | #define IS_BSS(p) (p.p_filesz < p.p_memsz) |
261 | | | 261 | |
262 | #ifndef MD_LOADSEG /* Allow processor ABI specific segment loads */ | | 262 | #ifndef MD_LOADSEG /* Allow processor ABI specific segment loads */ |
263 | #define MD_LOADSEG(a) /*CONSTCOND*/0 | | 263 | #define MD_LOADSEG(a) /*CONSTCOND*/0 |
264 | #endif | | 264 | #endif |
265 | | | 265 | |
266 | /* -------------------------------------------------------------------------- */ | | 266 | /* -------------------------------------------------------------------------- */ |
267 | | | 267 | |
268 | #define KERNALIGN_SMALL (1 << 12) /* XXX should depend on marks[] */ | | 268 | #define KERNALIGN_SMALL (1 << 12) /* XXX should depend on marks[] */ |
269 | #define KERNALIGN_LARGE (1 << 21) /* XXX should depend on marks[] */ | | 269 | #define KERNALIGN_LARGE (1 << 21) /* XXX should depend on marks[] */ |
270 | | | 270 | |
271 | /* | | 271 | /* |
272 | * Read some data from a file, and put it in the bootloader memory (local). | | 272 | * Read some data from a file, and put it in the bootloader memory (local). |
273 | */ | | 273 | */ |
274 | static int | | 274 | static int |
275 | ELFNAMEEND(readfile_local)(int fd, Elf_Off elfoff, void *addr, size_t size) | | 275 | ELFNAMEEND(readfile_local)(int fd, Elf_Off elfoff, void *addr, size_t size) |
276 | { | | 276 | { |
277 | ssize_t nr; | | 277 | ssize_t nr; |
278 | | | 278 | |
279 | if (lseek(fd, elfoff, SEEK_SET) == -1) { | | 279 | if (lseek(fd, elfoff, SEEK_SET) == -1) { |
280 | WARN(("lseek section headers")); | | 280 | WARN(("lseek section headers")); |
281 | return -1; | | 281 | return -1; |
282 | } | | 282 | } |
283 | nr = read(fd, addr, size); | | 283 | nr = read(fd, addr, size); |
284 | if (nr == -1) { | | 284 | if (nr == -1) { |
285 | WARN(("read section headers")); | | 285 | WARN(("read section headers")); |
286 | return -1; | | 286 | return -1; |
287 | } | | 287 | } |
288 | if (nr != (ssize_t)size) { | | 288 | if (nr != (ssize_t)size) { |
289 | errno = EIO; | | 289 | errno = EIO; |
290 | WARN(("read section headers")); | | 290 | WARN(("read section headers")); |
291 | return -1; | | 291 | return -1; |
292 | } | | 292 | } |
293 | | | 293 | |
294 | return 0; | | 294 | return 0; |
295 | } | | 295 | } |
296 | | | 296 | |
297 | /* | | 297 | /* |
298 | * Read some data from a file, and put it in wherever in memory (global). | | 298 | * Read some data from a file, and put it in wherever in memory (global). |
299 | */ | | 299 | */ |
300 | static int | | 300 | static int |
301 | ELFNAMEEND(readfile_global)(int fd, u_long offset, Elf_Off elfoff, | | 301 | ELFNAMEEND(readfile_global)(int fd, u_long offset, Elf_Off elfoff, |
302 | Elf_Addr addr, size_t size) | | 302 | Elf_Addr addr, size_t size) |
303 | { | | 303 | { |
304 | ssize_t nr; | | 304 | ssize_t nr; |
305 | | | 305 | |
306 | /* some ports dont use the offset */ | | 306 | /* some ports dont use the offset */ |
307 | (void)&offset; | | 307 | (void)&offset; |
308 | | | 308 | |
309 | if (lseek(fd, elfoff, SEEK_SET) == -1) { | | 309 | if (lseek(fd, elfoff, SEEK_SET) == -1) { |
310 | WARN(("lseek section")); | | 310 | WARN(("lseek section")); |
311 | return -1; | | 311 | return -1; |
312 | } | | 312 | } |
313 | nr = READ(fd, addr, size); | | 313 | nr = READ(fd, addr, size); |
314 | if (nr == -1) { | | 314 | if (nr == -1) { |
315 | WARN(("read section")); | | 315 | WARN(("read section")); |
316 | return -1; | | 316 | return -1; |
317 | } | | 317 | } |
318 | if (nr != (ssize_t)size) { | | 318 | if (nr != (ssize_t)size) { |
319 | errno = EIO; | | 319 | errno = EIO; |
320 | WARN(("read section")); | | 320 | WARN(("read section")); |
321 | return -1; | | 321 | return -1; |
322 | } | | 322 | } |
323 | | | 323 | |
324 | return 0; | | 324 | return 0; |
325 | } | | 325 | } |
326 | | | 326 | |
327 | /* | | 327 | /* |
328 | * Load a dynamic ELF binary into memory. Layout of the memory: | | 328 | * Load a dynamic ELF binary into memory. Layout of the memory: |
329 | * +------------+-----------------+-----------------+------------------+ | | 329 | * +------------+-----------------+-----------------+------------------+ |
330 | * | ELF HEADER | SECTION HEADERS | KERNEL SECTIONS | SYM+REL SECTIONS | | | 330 | * | ELF HEADER | SECTION HEADERS | KERNEL SECTIONS | SYM+REL SECTIONS | |
331 | * +------------+-----------------+-----------------+------------------+ | | 331 | * +------------+-----------------+-----------------+------------------+ |
332 | * The ELF HEADER start address is marks[MARK_END]. We then map the rest | | 332 | * The ELF HEADER start address is marks[MARK_END]. We then map the rest |
333 | * by increasing maxp. An alignment is enforced between the code sections. | | 333 | * by increasing maxp. An alignment is enforced between the code sections. |
334 | * | | 334 | * |
335 | * The offsets of the KERNEL and SYM+REL sections are relative to the start | | 335 | * The offsets of the KERNEL and SYM+REL sections are relative to the start |
336 | * address of the ELF HEADER. We just give the kernel a pointer to the ELF | | 336 | * address of the ELF HEADER. We just give the kernel a pointer to the ELF |
337 | * HEADER, and we let the kernel find the location and number of symbols by | | 337 | * HEADER, and we let the kernel find the location and number of symbols by |
338 | * itself. | | 338 | * itself. |
339 | */ | | 339 | */ |
340 | static int | | 340 | static int |
341 | ELFNAMEEND(loadfile_dynamic)(int fd, Elf_Ehdr *elf, u_long *marks, int flags) | | 341 | ELFNAMEEND(loadfile_dynamic)(int fd, Elf_Ehdr *elf, u_long *marks, int flags) |
342 | { | | 342 | { |
343 | const u_long offset = 0; | | 343 | const u_long offset = 0; |
344 | Elf_Shdr *shdr; | | 344 | Elf_Shdr *shdr; |
345 | Elf_Addr shpp, addr; | | 345 | Elf_Addr shpp, addr; |
346 | int i, j, loaded; | | 346 | int i, j, loaded; |
347 | size_t size, shdrsz, align; | | 347 | size_t size, shdrsz, align; |
348 | Elf_Addr maxp, elfp = 0; | | 348 | Elf_Addr maxp, elfp = 0; |
349 | int ret; | | 349 | int ret; |
350 | | | 350 | |
351 | maxp = marks[MARK_END]; | | 351 | maxp = marks[MARK_END]; |
352 | | | 352 | |
353 | internalize_ehdr(elf->e_ident[EI_DATA], elf); | | 353 | internalize_ehdr(elf->e_ident[EI_DATA], elf); |
354 | | | 354 | |
355 | if (elf->e_type != ET_REL) { | | 355 | if (elf->e_type != ET_REL) { |
356 | errno = EINVAL; | | 356 | errno = EINVAL; |
357 | return 1; | | 357 | return 1; |
358 | } | | 358 | } |
359 | | | 359 | |
360 | /* Create a local copy of the SECTION HEADERS. */ | | 360 | /* Create a local copy of the SECTION HEADERS. */ |
361 | shdrsz = elf->e_shnum * sizeof(Elf_Shdr); | | 361 | shdrsz = elf->e_shnum * sizeof(Elf_Shdr); |
362 | shdr = ALLOC(shdrsz); | | 362 | shdr = ALLOC(shdrsz); |
363 | ret = ELFNAMEEND(readfile_local)(fd, elf->e_shoff, shdr, shdrsz); | | 363 | ret = ELFNAMEEND(readfile_local)(fd, elf->e_shoff, shdr, shdrsz); |
364 | if (ret == -1) { | | 364 | if (ret == -1) { |
365 | goto out; | | 365 | goto out; |
366 | } | | 366 | } |
367 | | | 367 | |
368 | /* | | 368 | /* |
369 | * Load the ELF HEADER. Update the section offset, to be relative to | | 369 | * Load the ELF HEADER. Update the section offset, to be relative to |
370 | * elfp. | | 370 | * elfp. |
371 | */ | | 371 | */ |
372 | elf->e_phoff = 0; | | 372 | elf->e_phoff = 0; |
373 | elf->e_shoff = sizeof(Elf_Ehdr); | | 373 | elf->e_shoff = sizeof(Elf_Ehdr); |
374 | elf->e_phentsize = 0; | | 374 | elf->e_phentsize = 0; |
375 | elf->e_phnum = 0; | | 375 | elf->e_phnum = 0; |
376 | elfp = maxp; | | 376 | elfp = maxp; |
377 | externalize_ehdr(elf->e_ident[EI_DATA], elf); | | 377 | externalize_ehdr(elf->e_ident[EI_DATA], elf); |
378 | BCOPY(elf, elfp, sizeof(*elf)); | | 378 | BCOPY(elf, elfp, sizeof(*elf)); |
379 | internalize_ehdr(elf->e_ident[EI_DATA], elf); | | 379 | internalize_ehdr(elf->e_ident[EI_DATA], elf); |
380 | maxp += sizeof(Elf_Ehdr); | | 380 | maxp += sizeof(Elf_Ehdr); |
381 | | | 381 | |
382 | #ifndef _STANDALONE | | 382 | #ifndef _STANDALONE |
383 | for (i = 0; i < elf->e_shnum; i++) | | 383 | for (i = 0; i < elf->e_shnum; i++) |
384 | internalize_shdr(elf->e_ident[EI_DATA], &shdr[i]); | | 384 | internalize_shdr(elf->e_ident[EI_DATA], &shdr[i]); |
385 | #endif | | 385 | #endif |
386 | | | 386 | |
387 | /* Save location of the SECTION HEADERS. */ | | 387 | /* Save location of the SECTION HEADERS. */ |
388 | shpp = maxp; | | 388 | shpp = maxp; |
389 | maxp += roundup(shdrsz, ELFROUND); | | 389 | maxp += roundup(shdrsz, ELFROUND); |
390 | | | 390 | |
391 | /* | | 391 | /* |
392 | * Load the KERNEL SECTIONS. | | 392 | * Load the KERNEL SECTIONS. |
393 | */ | | 393 | */ |
394 | maxp = roundup(maxp, KERNALIGN_SMALL); | | 394 | maxp = roundup(maxp, KERNALIGN_SMALL); |
395 | for (i = 0; i < elf->e_shnum; i++) { | | 395 | for (i = 0; i < elf->e_shnum; i++) { |
396 | if (!(shdr[i].sh_flags & SHF_ALLOC)) { | | 396 | if (!(shdr[i].sh_flags & SHF_ALLOC)) { |
397 | continue; | | 397 | continue; |
398 | } | | 398 | } |
399 | size = (size_t)shdr[i].sh_size; | | 399 | size = (size_t)shdr[i].sh_size; |
400 | if (size <= KERNALIGN_SMALL) { | | 400 | if (size <= KERNALIGN_SMALL) { |
401 | align = KERNALIGN_SMALL; | | 401 | align = KERNALIGN_SMALL; |
402 | } else { | | 402 | } else { |
403 | align = KERNALIGN_LARGE; | | 403 | align = KERNALIGN_LARGE; |
404 | } | | 404 | } |
405 | addr = roundup(maxp, align); | | 405 | addr = roundup(maxp, align); |
406 | | | 406 | |
407 | loaded = 0; | | 407 | loaded = 0; |
408 | switch (shdr[i].sh_type) { | | 408 | switch (shdr[i].sh_type) { |
409 | case SHT_NOBITS: | | 409 | case SHT_NOBITS: |
410 | /* Zero out bss. */ | | 410 | /* Zero out bss. */ |
411 | BZERO(addr, size); | | 411 | BZERO(addr, size); |
412 | loaded = 1; | | 412 | loaded = 1; |
413 | break; | | 413 | break; |
414 | case SHT_PROGBITS: | | 414 | case SHT_PROGBITS: |
415 | ret = ELFNAMEEND(readfile_global)(fd, offset, | | 415 | ret = ELFNAMEEND(readfile_global)(fd, offset, |
416 | shdr[i].sh_offset, addr, size); | | 416 | shdr[i].sh_offset, addr, size); |
417 | if (ret == -1) { | | 417 | if (ret == -1) { |
418 | goto out; | | 418 | goto out; |
419 | } | | 419 | } |
420 | loaded = 1; | | 420 | loaded = 1; |
421 | break; | | 421 | break; |
422 | default: | | 422 | default: |
423 | loaded = 0; | | 423 | loaded = 0; |
424 | break; | | 424 | break; |
425 | } | | 425 | } |
426 | | | 426 | |
427 | if (loaded) { | | 427 | if (loaded) { |
428 | shdr[i].sh_offset = addr - elfp; | | 428 | shdr[i].sh_offset = addr - elfp; |
429 | maxp = roundup(addr + size, align); | | 429 | maxp = roundup(addr + size, align); |
430 | } | | 430 | } |
431 | } | | 431 | } |
432 | maxp = roundup(maxp, KERNALIGN_LARGE); | | 432 | maxp = roundup(maxp, KERNALIGN_LARGE); |
433 | | | 433 | |
434 | /* | | 434 | /* |
435 | * Load the SYM+REL SECTIONS. | | 435 | * Load the SYM+REL SECTIONS. |
436 | */ | | 436 | */ |
437 | maxp = roundup(maxp, ELFROUND); | | 437 | maxp = roundup(maxp, ELFROUND); |
438 | for (i = 0; i < elf->e_shnum; i++) { | | 438 | for (i = 0; i < elf->e_shnum; i++) { |
439 | addr = maxp; | | 439 | addr = maxp; |
440 | size = (size_t)shdr[i].sh_size; | | 440 | size = (size_t)shdr[i].sh_size; |
441 | | | 441 | |
442 | switch (shdr[i].sh_type) { | | 442 | switch (shdr[i].sh_type) { |
443 | case SHT_STRTAB: | | 443 | case SHT_STRTAB: |
444 | for (j = 0; j < elf->e_shnum; j++) | | 444 | for (j = 0; j < elf->e_shnum; j++) |
445 | if (shdr[j].sh_type == SHT_SYMTAB && | | 445 | if (shdr[j].sh_type == SHT_SYMTAB && |
446 | shdr[j].sh_link == (unsigned int)i) | | 446 | shdr[j].sh_link == (unsigned int)i) |
447 | goto havesym; | | 447 | goto havesym; |
448 | if (elf->e_shstrndx == i) | | 448 | if (elf->e_shstrndx == i) |
449 | goto havesym; | | 449 | goto havesym; |
450 | /* | | 450 | /* |
451 | * Don't bother with any string table that isn't | | 451 | * Don't bother with any string table that isn't |
452 | * referenced by a symbol table. | | 452 | * referenced by a symbol table. |
453 | */ | | 453 | */ |
454 | shdr[i].sh_offset = 0; | | 454 | shdr[i].sh_offset = 0; |
455 | break; | | 455 | break; |
456 | havesym: | | 456 | havesym: |
457 | case SHT_REL: | | 457 | case SHT_REL: |
458 | case SHT_RELA: | | 458 | case SHT_RELA: |
459 | case SHT_SYMTAB: | | 459 | case SHT_SYMTAB: |
460 | ret = ELFNAMEEND(readfile_global)(fd, offset, | | 460 | ret = ELFNAMEEND(readfile_global)(fd, offset, |
461 | shdr[i].sh_offset, addr, size); | | 461 | shdr[i].sh_offset, addr, size); |
462 | if (ret == -1) { | | 462 | if (ret == -1) { |
463 | goto out; | | 463 | goto out; |
464 | } | | 464 | } |
465 | shdr[i].sh_offset = maxp - elfp; | | 465 | shdr[i].sh_offset = maxp - elfp; |
466 | maxp += roundup(size, ELFROUND); | | 466 | maxp += roundup(size, ELFROUND); |
467 | break; | | 467 | break; |
468 | } | | 468 | } |
469 | } | | 469 | } |
470 | maxp = roundup(maxp, KERNALIGN_SMALL); | | 470 | maxp = roundup(maxp, KERNALIGN_SMALL); |
471 | | | 471 | |
472 | /* | | 472 | /* |
473 | * Finally, load the SECTION HEADERS. | | 473 | * Finally, load the SECTION HEADERS. |
474 | */ | | 474 | */ |
475 | #ifndef _STANDALONE | | 475 | #ifndef _STANDALONE |
476 | for (i = 0; i < elf->e_shnum; i++) | | 476 | for (i = 0; i < elf->e_shnum; i++) |
477 | externalize_shdr(elf->e_ident[EI_DATA], &shdr[i]); | | 477 | externalize_shdr(elf->e_ident[EI_DATA], &shdr[i]); |
478 | #endif | | 478 | #endif |
479 | BCOPY(shdr, shpp, shdrsz); | | 479 | BCOPY(shdr, shpp, shdrsz); |
480 | | | 480 | |
481 | DEALLOC(shdr, shdrsz); | | 481 | DEALLOC(shdr, shdrsz); |
482 | | | 482 | |
483 | /* | | 483 | /* |
484 | * Just update MARK_SYM and MARK_END without touching the rest. | | 484 | * Just update MARK_SYM and MARK_END without touching the rest. |
485 | */ | | 485 | */ |
486 | marks[MARK_SYM] = LOADADDR(elfp); | | 486 | marks[MARK_SYM] = LOADADDR(elfp); |
487 | marks[MARK_END] = LOADADDR(maxp); | | 487 | marks[MARK_END] = LOADADDR(maxp); |
488 | return 0; | | 488 | return 0; |
489 | | | 489 | |
490 | out: | | 490 | out: |
491 | DEALLOC(shdr, shdrsz); | | 491 | DEALLOC(shdr, shdrsz); |
492 | return 1; | | 492 | return 1; |
493 | } | | 493 | } |
494 | | | 494 | |
495 | /* -------------------------------------------------------------------------- */ | | 495 | /* -------------------------------------------------------------------------- */ |
496 | | | 496 | |
497 | /* | | 497 | /* |
498 | * See comment below. This function is in charge of loading the SECTION HEADERS. | | 498 | * See comment below. This function is in charge of loading the SECTION HEADERS. |
499 | */ | | 499 | */ |
500 | static int | | 500 | static int |
501 | ELFNAMEEND(loadsym)(int fd, Elf_Ehdr *elf, Elf_Addr maxp, Elf_Addr elfp, | | 501 | ELFNAMEEND(loadsym)(int fd, Elf_Ehdr *elf, Elf_Addr maxp, Elf_Addr elfp, |
502 | u_long *marks, int flags, Elf_Addr *nmaxp) | | 502 | u_long *marks, int flags, Elf_Addr *nmaxp) |
503 | { | | 503 | { |
504 | const u_long offset = marks[MARK_START]; | | 504 | const u_long offset = marks[MARK_START]; |
505 | int boot_load_ctf = 1; | | 505 | int boot_load_ctf = 1; |
506 | Elf_Shdr *shp; | | 506 | Elf_Shdr *shp; |
507 | Elf_Addr shpp; | | 507 | Elf_Addr shpp; |
508 | char *shstr = NULL; | | 508 | char *shstr = NULL; |
509 | size_t sz; | | 509 | size_t sz; |
510 | size_t i, j, shstrsz = 0; | | 510 | size_t i, j, shstrsz = 0; |
511 | struct __packed { | | 511 | struct __packed { |
512 | Elf_Nhdr nh; | | 512 | Elf_Nhdr nh; |
513 | uint8_t name[ELF_NOTE_NETBSD_NAMESZ + 1]; | | 513 | uint8_t name[ELF_NOTE_NETBSD_NAMESZ + 1]; |
514 | uint8_t desc[ELF_NOTE_NETBSD_DESCSZ]; | | 514 | uint8_t desc[ELF_NOTE_NETBSD_DESCSZ]; |
515 | } note; | | 515 | } note; |
516 | int first; | | 516 | int first; |
517 | int ret; | | 517 | int ret; |
518 | | | 518 | |
519 | sz = elf->e_shnum * sizeof(Elf_Shdr); | | 519 | sz = elf->e_shnum * sizeof(Elf_Shdr); |
520 | shp = ALLOC(sz); | | 520 | shp = ALLOC(sz); |
521 | ret = ELFNAMEEND(readfile_local)(fd, elf->e_shoff, shp, sz); | | 521 | ret = ELFNAMEEND(readfile_local)(fd, elf->e_shoff, shp, sz); |
522 | if (ret == -1) { | | 522 | if (ret == -1) { |
523 | goto out; | | 523 | goto out; |
524 | } | | 524 | } |
525 | | | 525 | |
526 | shpp = maxp; | | 526 | shpp = maxp; |
527 | maxp += roundup(sz, ELFROUND); | | 527 | maxp += roundup(sz, ELFROUND); |
528 | | | 528 | |
529 | #ifndef _STANDALONE | | 529 | #ifndef _STANDALONE |
530 | for (i = 0; i < elf->e_shnum; i++) | | 530 | for (i = 0; i < elf->e_shnum; i++) |
531 | internalize_shdr(elf->e_ident[EI_DATA], &shp[i]); | | 531 | internalize_shdr(elf->e_ident[EI_DATA], &shp[i]); |
532 | #endif | | 532 | #endif |
533 | | | 533 | |
534 | /* | | 534 | /* |
535 | * First load the section names section. Only useful for CTF. | | 535 | * First load the section names section. Only useful for CTF. |
536 | */ | | 536 | */ |
537 | if (boot_load_ctf && (elf->e_shstrndx != SHN_UNDEF)) { | | 537 | if (boot_load_ctf && (elf->e_shstrndx != SHN_UNDEF)) { |
538 | Elf_Off shstroff = shp[elf->e_shstrndx].sh_offset; | | 538 | Elf_Off shstroff = shp[elf->e_shstrndx].sh_offset; |
539 | shstrsz = shp[elf->e_shstrndx].sh_size; | | 539 | shstrsz = shp[elf->e_shstrndx].sh_size; |
540 | if (flags & LOAD_SYM) { | | 540 | if (flags & LOAD_SYM) { |
541 | ret = ELFNAMEEND(readfile_global)(fd, offset, | | 541 | ret = ELFNAMEEND(readfile_global)(fd, offset, |
542 | shstroff, maxp, shstrsz); | | 542 | shstroff, maxp, shstrsz); |
543 | if (ret == -1) { | | 543 | if (ret == -1) { |
544 | goto out; | | 544 | goto out; |
545 | } | | 545 | } |
546 | } | | 546 | } |
547 | | | 547 | |
548 | /* Create a local copy */ | | 548 | /* Create a local copy */ |
549 | shstr = ALLOC(shstrsz); | | 549 | shstr = ALLOC(shstrsz); |
550 | ret = ELFNAMEEND(readfile_local)(fd, shstroff, shstr, shstrsz); | | 550 | ret = ELFNAMEEND(readfile_local)(fd, shstroff, shstr, shstrsz); |
551 | if (ret == -1) { | | 551 | if (ret == -1) { |
552 | goto out; | | 552 | goto out; |
553 | } | | 553 | } |
554 | shp[elf->e_shstrndx].sh_offset = maxp - elfp; | | 554 | shp[elf->e_shstrndx].sh_offset = maxp - elfp; |
555 | maxp += roundup(shstrsz, ELFROUND); | | 555 | maxp += roundup(shstrsz, ELFROUND); |
556 | } | | 556 | } |
557 | | | 557 | |
558 | /* | | 558 | /* |
559 | * Now load the symbol sections themselves. Make sure the sections are | | 559 | * Now load the symbol sections themselves. Make sure the sections are |
560 | * ELFROUND-aligned. Update sh_offset to be relative to elfp. Set it to | | 560 | * ELFROUND-aligned. Update sh_offset to be relative to elfp. Set it to |
561 | * zero when we don't want the sections to be taken care of, the kernel | | 561 | * zero when we don't want the sections to be taken care of, the kernel |
562 | * will properly skip them. | | 562 | * will properly skip them. |
563 | */ | | 563 | */ |
564 | first = 1; | | 564 | first = 1; |
565 | for (i = 1; i < elf->e_shnum; i++) { | | 565 | for (i = 1; i < elf->e_shnum; i++) { |
566 | if (i == elf->e_shstrndx) { | | 566 | if (i == elf->e_shstrndx) { |
567 | /* already loaded this section */ | | 567 | /* already loaded this section */ |
568 | continue; | | 568 | continue; |
569 | } | | 569 | } |
570 | | | 570 | |
571 | switch (shp[i].sh_type) { | | 571 | switch (shp[i].sh_type) { |
572 | case SHT_PROGBITS: | | 572 | case SHT_PROGBITS: |
573 | if (boot_load_ctf && shstr) { | | 573 | if (boot_load_ctf && shstr) { |
574 | /* got a CTF section? */ | | 574 | /* got a CTF section? */ |
575 | if (strncmp(&shstr[shp[i].sh_name], | | 575 | if (strncmp(&shstr[shp[i].sh_name], |
576 | ".SUNW_ctf", 10) == 0) { | | 576 | ".SUNW_ctf", 10) == 0) { |
577 | goto havesym; | | 577 | goto havesym; |
578 | } | | 578 | } |
579 | } | | 579 | } |
580 | | | 580 | |
581 | shp[i].sh_offset = 0; | | 581 | shp[i].sh_offset = 0; |
582 | break; | | 582 | break; |
583 | case SHT_STRTAB: | | 583 | case SHT_STRTAB: |
584 | for (j = 1; j < elf->e_shnum; j++) | | 584 | for (j = 1; j < elf->e_shnum; j++) |
585 | if (shp[j].sh_type == SHT_SYMTAB && | | 585 | if (shp[j].sh_type == SHT_SYMTAB && |
586 | shp[j].sh_link == (unsigned int)i) | | 586 | shp[j].sh_link == (unsigned int)i) |
587 | goto havesym; | | 587 | goto havesym; |
588 | /* | | 588 | /* |
589 | * Don't bother with any string table that isn't | | 589 | * Don't bother with any string table that isn't |
590 | * referenced by a symbol table. | | 590 | * referenced by a symbol table. |
591 | */ | | 591 | */ |
592 | shp[i].sh_offset = 0; | | 592 | shp[i].sh_offset = 0; |
593 | break; | | 593 | break; |
594 | havesym: | | 594 | havesym: |
595 | case SHT_SYMTAB: | | 595 | case SHT_SYMTAB: |
596 | if (flags & LOAD_SYM) { | | 596 | if (flags & LOAD_SYM) { |
597 | PROGRESS(("%s%ld", first ? " [" : "+", | | 597 | PROGRESS(("%s%ld", first ? " [" : "+", |
598 | (u_long)shp[i].sh_size)); | | 598 | (u_long)shp[i].sh_size)); |
599 | ret = ELFNAMEEND(readfile_global)(fd, offset, | | 599 | ret = ELFNAMEEND(readfile_global)(fd, offset, |
600 | shp[i].sh_offset, maxp, shp[i].sh_size); | | 600 | shp[i].sh_offset, maxp, shp[i].sh_size); |
601 | if (ret == -1) { | | 601 | if (ret == -1) { |
602 | goto out; | | 602 | goto out; |
603 | } | | 603 | } |
604 | } | | 604 | } |
605 | shp[i].sh_offset = maxp - elfp; | | 605 | shp[i].sh_offset = maxp - elfp; |
606 | maxp += roundup(shp[i].sh_size, ELFROUND); | | 606 | maxp += roundup(shp[i].sh_size, ELFROUND); |
607 | first = 0; | | 607 | first = 0; |
608 | break; | | 608 | break; |
609 | case SHT_NOTE: | | 609 | case SHT_NOTE: |
610 | if ((flags & LOAD_NOTE) == 0) | | 610 | if ((flags & LOAD_NOTE) == 0) |
611 | break; | | 611 | break; |
612 | if (shp[i].sh_size < sizeof(note)) { | | 612 | if (shp[i].sh_size < sizeof(note)) { |
613 | shp[i].sh_offset = 0; | | 613 | shp[i].sh_offset = 0; |
614 | break; | | 614 | break; |
615 | } | | 615 | } |
616 | | | 616 | |
617 | ret = ELFNAMEEND(readfile_local)(fd, shp[i].sh_offset, | | 617 | ret = ELFNAMEEND(readfile_local)(fd, shp[i].sh_offset, |
618 | ¬e, sizeof(note)); | | 618 | ¬e, sizeof(note)); |
619 | if (ret == -1) { | | 619 | if (ret == -1) { |
620 | goto out; | | 620 | goto out; |
621 | } | | 621 | } |
622 | | | 622 | |
623 | if (note.nh.n_namesz == ELF_NOTE_NETBSD_NAMESZ && | | 623 | if (note.nh.n_namesz == ELF_NOTE_NETBSD_NAMESZ && |
624 | note.nh.n_descsz == ELF_NOTE_NETBSD_DESCSZ && | | 624 | note.nh.n_descsz == ELF_NOTE_NETBSD_DESCSZ && |
625 | note.nh.n_type == ELF_NOTE_TYPE_NETBSD_TAG && | | 625 | note.nh.n_type == ELF_NOTE_TYPE_NETBSD_TAG && |
626 | memcmp(note.name, ELF_NOTE_NETBSD_NAME, | | 626 | memcmp(note.name, ELF_NOTE_NETBSD_NAME, |
627 | sizeof(note.name)) == 0) { | | 627 | sizeof(note.name)) == 0) { |
628 | memcpy(&netbsd_version, ¬e.desc, | | 628 | memcpy(&netbsd_version, ¬e.desc, |
629 | sizeof(netbsd_version)); | | 629 | sizeof(netbsd_version)); |
630 | } | | 630 | } |
631 | shp[i].sh_offset = 0; | | 631 | shp[i].sh_offset = 0; |
632 | break; | | 632 | break; |
633 | default: | | 633 | default: |
634 | shp[i].sh_offset = 0; | | 634 | shp[i].sh_offset = 0; |
635 | break; | | 635 | break; |
636 | } | | 636 | } |
637 | } | | 637 | } |
638 | if (flags & LOAD_SYM) { | | 638 | if (flags & LOAD_SYM) { |
639 | #ifndef _STANDALONE | | 639 | #ifndef _STANDALONE |
640 | for (i = 0; i < elf->e_shnum; i++) | | 640 | for (i = 0; i < elf->e_shnum; i++) |
641 | externalize_shdr(elf->e_ident[EI_DATA], &shp[i]); | | 641 | externalize_shdr(elf->e_ident[EI_DATA], &shp[i]); |
642 | #endif | | 642 | #endif |
643 | BCOPY(shp, shpp, sz); | | 643 | BCOPY(shp, shpp, sz); |
644 | | | 644 | |
645 | if (first == 0) | | 645 | if (first == 0) |
646 | PROGRESS(("]")); | | 646 | PROGRESS(("]")); |
647 | } | | 647 | } |
648 | | | 648 | |
649 | *nmaxp = maxp; | | 649 | *nmaxp = maxp; |
650 | DEALLOC(shp, sz); | | 650 | DEALLOC(shp, sz); |
651 | if (shstr != NULL) | | 651 | if (shstr != NULL) |
652 | DEALLOC(shstr, shstrsz); | | 652 | DEALLOC(shstr, shstrsz); |
653 | return 0; | | 653 | return 0; |
654 | | | 654 | |
655 | out: | | 655 | out: |
656 | DEALLOC(shp, sz); | | 656 | DEALLOC(shp, sz); |
657 | if (shstr != NULL) | | 657 | if (shstr != NULL) |
658 | DEALLOC(shstr, shstrsz); | | 658 | DEALLOC(shstr, shstrsz); |
659 | return -1; | | 659 | return -1; |
660 | } | | 660 | } |
661 | | | 661 | |
662 | /* -------------------------------------------------------------------------- */ | | 662 | /* -------------------------------------------------------------------------- */ |
663 | | | 663 | |
664 | /* | | 664 | /* |
665 | * Load a static ELF binary into memory. Layout of the memory: | | 665 | * Load a static ELF binary into memory. Layout of the memory: |
666 | * +-----------------+------------+-----------------+-----------------+ | | 666 | * +-----------------+------------+-----------------+-----------------+ |
667 | * | KERNEL SEGMENTS | ELF HEADER | SECTION HEADERS | SYMBOL SECTIONS | | | 667 | * | KERNEL SEGMENTS | ELF HEADER | SECTION HEADERS | SYMBOL SECTIONS | |
668 | * +-----------------+------------+-----------------+-----------------+ | | 668 | * +-----------------+------------+-----------------+-----------------+ |
669 | * The KERNEL SEGMENTS start address is fixed by the segments themselves. We | | 669 | * The KERNEL SEGMENTS start address is fixed by the segments themselves. We |
670 | * then map the rest by increasing maxp. | | 670 | * then map the rest by increasing maxp. |
671 | * | | 671 | * |
672 | * The offsets of the SYMBOL SECTIONS are relative to the start address of the | | 672 | * The offsets of the SYMBOL SECTIONS are relative to the start address of the |
673 | * ELF HEADER. The shdr offset of ELF HEADER points to SECTION HEADERS. | | 673 | * ELF HEADER. The shdr offset of ELF HEADER points to SECTION HEADERS. |
674 | * | | 674 | * |
675 | * We just give the kernel a pointer to the ELF HEADER, which is enough for it | | 675 | * We just give the kernel a pointer to the ELF HEADER, which is enough for it |
676 | * to find the location and number of symbols by itself later. | | 676 | * to find the location and number of symbols by itself later. |
677 | */ | | 677 | */ |
678 | static int | | 678 | static int |
679 | ELFNAMEEND(loadfile_static)(int fd, Elf_Ehdr *elf, u_long *marks, int flags) | | 679 | ELFNAMEEND(loadfile_static)(int fd, Elf_Ehdr *elf, u_long *marks, int flags) |
680 | { | | 680 | { |
681 | const u_long offset = marks[MARK_START]; | | 681 | const u_long offset = marks[MARK_START]; |
682 | Elf_Phdr *phdr; | | 682 | Elf_Phdr *phdr; |
683 | int i, first; | | 683 | int i, first; |
684 | size_t sz; | | 684 | size_t sz; |
685 | Elf_Addr minp = ~0, maxp = 0, pos = 0, elfp = 0; | | 685 | Elf_Addr minp = ~0, maxp = 0, pos = 0, elfp = 0; |
686 | int ret; | | 686 | int ret; |
687 | | | 687 | |
688 | /* for ports that define progress to nothing */ | | 688 | /* for ports that define progress to nothing */ |
689 | (void)&first; | | 689 | (void)&first; |
690 | | | 690 | |
691 | /* have not seen a data segment so far */ | | 691 | /* have not seen a data segment so far */ |
692 | marks[MARK_DATA] = 0; | | 692 | marks[MARK_DATA] = 0; |
693 | | | 693 | |
694 | internalize_ehdr(elf->e_ident[EI_DATA], elf); | | 694 | internalize_ehdr(elf->e_ident[EI_DATA], elf); |
695 | | | 695 | |
696 | sz = elf->e_phnum * sizeof(Elf_Phdr); | | 696 | sz = elf->e_phnum * sizeof(Elf_Phdr); |
697 | phdr = ALLOC(sz); | | 697 | phdr = ALLOC(sz); |
698 | ret = ELFNAMEEND(readfile_local)(fd, elf->e_phoff, phdr, sz); | | 698 | ret = ELFNAMEEND(readfile_local)(fd, elf->e_phoff, phdr, sz); |
699 | if (ret == -1) { | | 699 | if (ret == -1) { |
700 | goto freephdr; | | 700 | goto freephdr; |
701 | } | | 701 | } |
702 | | | 702 | |
703 | first = 1; | | 703 | first = 1; |
704 | for (i = 0; i < elf->e_phnum; i++) { | | 704 | for (i = 0; i < elf->e_phnum; i++) { |
705 | internalize_phdr(elf->e_ident[EI_DATA], &phdr[i]); | | 705 | internalize_phdr(elf->e_ident[EI_DATA], &phdr[i]); |
706 | | | 706 | |
707 | if (MD_LOADSEG(&phdr[i])) | | 707 | if (MD_LOADSEG(&phdr[i])) |
708 | goto loadseg; | | 708 | goto loadseg; |
709 | | | 709 | |
710 | if (phdr[i].p_type != PT_LOAD || | | 710 | if (phdr[i].p_type != PT_LOAD || |
711 | (phdr[i].p_flags & (PF_W|PF_X)) == 0) | | 711 | (phdr[i].p_flags & (PF_W|PF_R|PF_X)) == 0) |
712 | continue; | | 712 | continue; |
713 | | | 713 | |
714 | if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) || | | 714 | if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) || |
715 | (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) { | | 715 | (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) { |
716 | loadseg: | | 716 | loadseg: |
717 | /* XXX: Assume first address is lowest */ | | 717 | /* XXX: Assume first address is lowest */ |
718 | if (marks[MARK_DATA] == 0 && IS_DATA(phdr[i])) | | 718 | if (marks[MARK_DATA] == 0 && IS_DATA(phdr[i])) |
719 | marks[MARK_DATA] = LOADADDR(phdr[i].p_vaddr); | | 719 | marks[MARK_DATA] = LOADADDR(phdr[i].p_vaddr); |
720 | | | 720 | |
721 | /* Read in segment. */ | | 721 | /* Read in segment. */ |
722 | PROGRESS(("%s%lu", first ? "" : "+", | | 722 | PROGRESS(("%s%lu", first ? "" : "+", |
723 | (u_long)phdr[i].p_filesz)); | | 723 | (u_long)phdr[i].p_filesz)); |
724 | | | 724 | |
725 | ret = ELFNAMEEND(readfile_global)(fd, offset, | | 725 | ret = ELFNAMEEND(readfile_global)(fd, offset, |
726 | phdr[i].p_offset, phdr[i].p_vaddr, | | 726 | phdr[i].p_offset, phdr[i].p_vaddr, |
727 | phdr[i].p_filesz); | | 727 | phdr[i].p_filesz); |
728 | if (ret == -1) { | | 728 | if (ret == -1) { |
729 | goto freephdr; | | 729 | goto freephdr; |
730 | } | | 730 | } |
731 | | | 731 | |
732 | first = 0; | | 732 | first = 0; |
733 | } | | 733 | } |
734 | if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT|COUNT_TEXT))) || | | 734 | if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT|COUNT_TEXT))) || |
735 | (IS_DATA(phdr[i]) && (flags & (LOAD_DATA|COUNT_DATA)))) { | | 735 | (IS_DATA(phdr[i]) && (flags & (LOAD_DATA|COUNT_DATA)))) { |
736 | /* XXX: Assume first address is lowest */ | | 736 | /* XXX: Assume first address is lowest */ |
737 | if (marks[MARK_DATA] == 0 && IS_DATA(phdr[i])) | | 737 | if (marks[MARK_DATA] == 0 && IS_DATA(phdr[i])) |
738 | marks[MARK_DATA] = LOADADDR(phdr[i].p_vaddr); | | 738 | marks[MARK_DATA] = LOADADDR(phdr[i].p_vaddr); |
739 | | | 739 | |
740 | pos = phdr[i].p_vaddr; | | 740 | pos = phdr[i].p_vaddr; |
741 | if (minp > pos) | | 741 | if (minp > pos) |
742 | minp = pos; | | 742 | minp = pos; |
743 | pos += phdr[i].p_filesz; | | 743 | pos += phdr[i].p_filesz; |
744 | if (maxp < pos) | | 744 | if (maxp < pos) |
745 | maxp = pos; | | 745 | maxp = pos; |
746 | } | | 746 | } |
747 | | | 747 | |
748 | /* Zero out bss. */ | | 748 | /* Zero out bss. */ |
749 | if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) { | | 749 | if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) { |
750 | PROGRESS(("+%lu", | | 750 | PROGRESS(("+%lu", |
751 | (u_long)(phdr[i].p_memsz - phdr[i].p_filesz))); | | 751 | (u_long)(phdr[i].p_memsz - phdr[i].p_filesz))); |
752 | BZERO((phdr[i].p_vaddr + phdr[i].p_filesz), | | 752 | BZERO((phdr[i].p_vaddr + phdr[i].p_filesz), |
753 | phdr[i].p_memsz - phdr[i].p_filesz); | | 753 | phdr[i].p_memsz - phdr[i].p_filesz); |
754 | } | | 754 | } |
755 | if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) { | | 755 | if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) { |
756 | pos += phdr[i].p_memsz - phdr[i].p_filesz; | | 756 | pos += phdr[i].p_memsz - phdr[i].p_filesz; |
757 | if (maxp < pos) | | 757 | if (maxp < pos) |
758 | maxp = pos; | | 758 | maxp = pos; |
759 | } | | 759 | } |
760 | } | | 760 | } |
761 | DEALLOC(phdr, sz); | | 761 | DEALLOC(phdr, sz); |
762 | maxp = roundup(maxp, ELFROUND); | | 762 | maxp = roundup(maxp, ELFROUND); |
763 | | | 763 | |
764 | /* | | 764 | /* |
765 | * Load the ELF HEADER, SECTION HEADERS and possibly the SYMBOL | | 765 | * Load the ELF HEADER, SECTION HEADERS and possibly the SYMBOL |
766 | * SECTIONS. | | 766 | * SECTIONS. |
767 | */ | | 767 | */ |
768 | if (flags & (LOAD_HDR|COUNT_HDR)) { | | 768 | if (flags & (LOAD_HDR|COUNT_HDR)) { |
769 | elfp = maxp; | | 769 | elfp = maxp; |
770 | maxp += sizeof(Elf_Ehdr); | | 770 | maxp += sizeof(Elf_Ehdr); |
771 | } | | 771 | } |
772 | if (flags & (LOAD_SYM|COUNT_SYM)) { | | 772 | if (flags & (LOAD_SYM|COUNT_SYM)) { |
773 | if (ELFNAMEEND(loadsym)(fd, elf, maxp, elfp, marks, flags, | | 773 | if (ELFNAMEEND(loadsym)(fd, elf, maxp, elfp, marks, flags, |
774 | &maxp) == -1) { | | 774 | &maxp) == -1) { |
775 | return 1; | | 775 | return 1; |
776 | } | | 776 | } |
777 | } | | 777 | } |
778 | | | 778 | |
779 | /* | | 779 | /* |
780 | * Update the ELF HEADER to give information relative to elfp. | | 780 | * Update the ELF HEADER to give information relative to elfp. |
781 | */ | | 781 | */ |
782 | if (flags & LOAD_HDR) { | | 782 | if (flags & LOAD_HDR) { |
783 | elf->e_phoff = 0; | | 783 | elf->e_phoff = 0; |
784 | elf->e_shoff = sizeof(Elf_Ehdr); | | 784 | elf->e_shoff = sizeof(Elf_Ehdr); |
785 | elf->e_phentsize = 0; | | 785 | elf->e_phentsize = 0; |
786 | elf->e_phnum = 0; | | 786 | elf->e_phnum = 0; |
787 | externalize_ehdr(elf->e_ident[EI_DATA], elf); | | 787 | externalize_ehdr(elf->e_ident[EI_DATA], elf); |
788 | BCOPY(elf, elfp, sizeof(*elf)); | | 788 | BCOPY(elf, elfp, sizeof(*elf)); |
789 | internalize_ehdr(elf->e_ident[EI_DATA], elf); | | 789 | internalize_ehdr(elf->e_ident[EI_DATA], elf); |
790 | } | | 790 | } |
791 | | | 791 | |
792 | marks[MARK_START] = LOADADDR(minp); | | 792 | marks[MARK_START] = LOADADDR(minp); |
793 | marks[MARK_ENTRY] = LOADADDR(elf->e_entry); | | 793 | marks[MARK_ENTRY] = LOADADDR(elf->e_entry); |
794 | marks[MARK_NSYM] = 1; /* XXX: Kernel needs >= 0 */ | | 794 | marks[MARK_NSYM] = 1; /* XXX: Kernel needs >= 0 */ |
795 | marks[MARK_SYM] = LOADADDR(elfp); | | 795 | marks[MARK_SYM] = LOADADDR(elfp); |
796 | marks[MARK_END] = LOADADDR(maxp); | | 796 | marks[MARK_END] = LOADADDR(maxp); |
797 | return 0; | | 797 | return 0; |
798 | | | 798 | |
799 | freephdr: | | 799 | freephdr: |
800 | DEALLOC(phdr, sz); | | 800 | DEALLOC(phdr, sz); |
801 | return 1; | | 801 | return 1; |
802 | } | | 802 | } |
803 | | | 803 | |
804 | /* -------------------------------------------------------------------------- */ | | 804 | /* -------------------------------------------------------------------------- */ |
805 | | | 805 | |
806 | int | | 806 | int |
807 | ELFNAMEEND(loadfile)(int fd, Elf_Ehdr *elf, u_long *marks, int flags) | | 807 | ELFNAMEEND(loadfile)(int fd, Elf_Ehdr *elf, u_long *marks, int flags) |
808 | { | | 808 | { |
809 | if (flags & LOAD_DYN) { | | 809 | if (flags & LOAD_DYN) { |
810 | return ELFNAMEEND(loadfile_dynamic)(fd, elf, marks, flags); | | 810 | return ELFNAMEEND(loadfile_dynamic)(fd, elf, marks, flags); |
811 | } else { | | 811 | } else { |
812 | return ELFNAMEEND(loadfile_static)(fd, elf, marks, flags); | | 812 | return ELFNAMEEND(loadfile_static)(fd, elf, marks, flags); |
813 | } | | 813 | } |
814 | } | | 814 | } |
815 | | | 815 | |
816 | #endif /* (ELFSIZE == 32 && BOOT_ELF32) || (ELFSIZE == 64 && BOOT_ELF64) */ | | 816 | #endif /* (ELFSIZE == 32 && BOOT_ELF32) || (ELFSIZE == 64 && BOOT_ELF64) */ |