elf.c revision 1.2.2.1 1 1.2.2.1 bouyer /* $NetBSD: elf.c,v 1.2.2.1 2000/11/20 20:39:22 bouyer Exp $ */
2 1.2.2.1 bouyer
3 1.2.2.1 bouyer /*-
4 1.2.2.1 bouyer * Copyright (c) 1999 Shin Takemura.
5 1.2.2.1 bouyer * All rights reserved.
6 1.2.2.1 bouyer *
7 1.2.2.1 bouyer * This software is part of the PocketBSD.
8 1.2.2.1 bouyer *
9 1.2.2.1 bouyer * Redistribution and use in source and binary forms, with or without
10 1.2.2.1 bouyer * modification, are permitted provided that the following conditions
11 1.2.2.1 bouyer * are met:
12 1.2.2.1 bouyer * 1. Redistributions of source code must retain the above copyright
13 1.2.2.1 bouyer * notice, this list of conditions and the following disclaimer.
14 1.2.2.1 bouyer * 2. Redistributions in binary form must reproduce the above copyright
15 1.2.2.1 bouyer * notice, this list of conditions and the following disclaimer in the
16 1.2.2.1 bouyer * documentation and/or other materials provided with the distribution.
17 1.2.2.1 bouyer * 3. All advertising materials mentioning features or use of this software
18 1.2.2.1 bouyer * must display the following acknowledgement:
19 1.2.2.1 bouyer * This product includes software developed by the PocketBSD project
20 1.2.2.1 bouyer * and its contributors.
21 1.2.2.1 bouyer * 4. Neither the name of the project nor the names of its contributors
22 1.2.2.1 bouyer * may be used to endorse or promote products derived from this software
23 1.2.2.1 bouyer * without specific prior written permission.
24 1.2.2.1 bouyer *
25 1.2.2.1 bouyer * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 1.2.2.1 bouyer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 1.2.2.1 bouyer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 1.2.2.1 bouyer * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 1.2.2.1 bouyer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 1.2.2.1 bouyer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 1.2.2.1 bouyer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 1.2.2.1 bouyer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 1.2.2.1 bouyer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 1.2.2.1 bouyer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 1.2.2.1 bouyer * SUCH DAMAGE.
36 1.2.2.1 bouyer *
37 1.2.2.1 bouyer */
38 1.2.2.1 bouyer #include <pbsdboot.h>
39 1.2.2.1 bouyer
40 1.2.2.1 bouyer #define ELFSIZE 32
41 1.2.2.1 bouyer //#include <sys/param.h>
42 1.2.2.1 bouyer //#include <sys/exec.h>
43 1.2.2.1 bouyer #include <sys/exec_elf.h>
44 1.2.2.1 bouyer
45 1.2.2.1 bouyer #if 1
46 1.2.2.1 bouyer #define LOAD_DEBUG_INFO
47 1.2.2.1 bouyer #define DEBUG_INFO_ALIGN 4096
48 1.2.2.1 bouyer #define ROUNDUP(a, n) ((((int)(a)) + (n)-1)/(n)*(n))
49 1.2.2.1 bouyer #endif
50 1.2.2.1 bouyer
51 1.2.2.1 bouyer static int
52 1.2.2.1 bouyer scanfile(int fd, caddr_t *start, caddr_t *end, caddr_t *entry, int load);
53 1.2.2.1 bouyer
54 1.2.2.1 bouyer static long total_bytes = 0;
55 1.2.2.1 bouyer
56 1.2.2.1 bouyer int
57 1.2.2.1 bouyer getinfo(int fd, caddr_t *start, caddr_t *end)
58 1.2.2.1 bouyer {
59 1.2.2.1 bouyer return (scanfile(fd, start, end, NULL, 0));
60 1.2.2.1 bouyer }
61 1.2.2.1 bouyer
62 1.2.2.1 bouyer int
63 1.2.2.1 bouyer loadfile(int fd, caddr_t *entry)
64 1.2.2.1 bouyer {
65 1.2.2.1 bouyer return (scanfile(fd, NULL, NULL, entry, 1));
66 1.2.2.1 bouyer }
67 1.2.2.1 bouyer
68 1.2.2.1 bouyer enum {
69 1.2.2.1 bouyer VMEM_CLEAR, VMEM_LOAD, VMEM_COPY
70 1.2.2.1 bouyer };
71 1.2.2.1 bouyer
72 1.2.2.1 bouyer int
73 1.2.2.1 bouyer vmem_sub(int opr, void* xxx, caddr_t addr, int nbytes, int *byte_count)
74 1.2.2.1 bouyer {
75 1.2.2.1 bouyer int n;
76 1.2.2.1 bouyer caddr_t end_addr, vaddr;
77 1.2.2.1 bouyer int count = 0;
78 1.2.2.1 bouyer int progress = 0;
79 1.2.2.1 bouyer int fd = (int)xxx;
80 1.2.2.1 bouyer caddr_t src_addr = (caddr_t)xxx;
81 1.2.2.1 bouyer
82 1.2.2.1 bouyer debug_printf(TEXT("loadfile_sub(%x-%x, %S)\n"),
83 1.2.2.1 bouyer addr, addr + nbytes,
84 1.2.2.1 bouyer opr == VMEM_CLEAR ? "clear" : (opr == VMEM_LOAD ? "load" : "copy"));
85 1.2.2.1 bouyer
86 1.2.2.1 bouyer for (end_addr = addr + nbytes;
87 1.2.2.1 bouyer addr < end_addr;
88 1.2.2.1 bouyer addr += n) {
89 1.2.2.1 bouyer if ((vaddr = vmem_get(addr, &n)) == NULL) {
90 1.2.2.1 bouyer debug_printf(TEXT("vmem_get(0x%x) failed.\n"), addr);
91 1.2.2.1 bouyer msg_printf(MSG_ERROR, whoami, TEXT("vmem_get(0x%x) failed.\n"), addr);
92 1.2.2.1 bouyer return (-1);
93 1.2.2.1 bouyer }
94 1.2.2.1 bouyer if (end_addr < addr + n) {
95 1.2.2.1 bouyer n = end_addr - addr;
96 1.2.2.1 bouyer }
97 1.2.2.1 bouyer switch (opr) {
98 1.2.2.1 bouyer case VMEM_CLEAR:
99 1.2.2.1 bouyer memset(vaddr, 0, n);
100 1.2.2.1 bouyer break;
101 1.2.2.1 bouyer case VMEM_LOAD:
102 1.2.2.1 bouyer if (read(fd, vaddr, n) != n) {
103 1.2.2.1 bouyer debug_printf(TEXT("read segment error.\n"));
104 1.2.2.1 bouyer msg_printf(MSG_ERROR, whoami, TEXT("read segment error.\n"));
105 1.2.2.1 bouyer return (-1);
106 1.2.2.1 bouyer }
107 1.2.2.1 bouyer break;
108 1.2.2.1 bouyer case VMEM_COPY:
109 1.2.2.1 bouyer memcpy(vaddr, src_addr, n);
110 1.2.2.1 bouyer src_addr += n;
111 1.2.2.1 bouyer break;
112 1.2.2.1 bouyer }
113 1.2.2.1 bouyer if (total_bytes != 0) {
114 1.2.2.1 bouyer int tmp_progress = *byte_count * 100 / total_bytes;
115 1.2.2.1 bouyer *byte_count += n;
116 1.2.2.1 bouyer if (progress != tmp_progress) {
117 1.2.2.1 bouyer progress = tmp_progress;
118 1.2.2.1 bouyer if (CheckCancel(progress)) {
119 1.2.2.1 bouyer return (-1);
120 1.2.2.1 bouyer }
121 1.2.2.1 bouyer }
122 1.2.2.1 bouyer }
123 1.2.2.1 bouyer }
124 1.2.2.1 bouyer return (0);
125 1.2.2.1 bouyer }
126 1.2.2.1 bouyer
127 1.2.2.1 bouyer
128 1.2.2.1 bouyer static int
129 1.2.2.1 bouyer scanfile(int fd, caddr_t *start, caddr_t *end, caddr_t *entry, int load)
130 1.2.2.1 bouyer {
131 1.2.2.1 bouyer Elf_Ehdr elfx, *elf = &elfx;
132 1.2.2.1 bouyer int i, first;
133 1.2.2.1 bouyer long byte_count;
134 1.2.2.1 bouyer int progress;
135 1.2.2.1 bouyer Elf_Shdr *shtbl = NULL;
136 1.2.2.1 bouyer Elf_Phdr *phtbl = NULL;
137 1.2.2.1 bouyer caddr_t min_addr, max_addr;
138 1.2.2.1 bouyer int sh_symidx, sh_stridx;
139 1.2.2.1 bouyer int dbg_hdr_size = sizeof(Elf_Ehdr) + sizeof(Elf_Shdr) * 2;
140 1.2.2.1 bouyer
141 1.2.2.1 bouyer if (lseek(fd, 0, SEEK_SET) == -1) {
142 1.2.2.1 bouyer debug_printf(TEXT("seek error\n"));
143 1.2.2.1 bouyer msg_printf(MSG_ERROR, whoami, TEXT("seek error.\n"));
144 1.2.2.1 bouyer goto error_cleanup;
145 1.2.2.1 bouyer }
146 1.2.2.1 bouyer if (read(fd, (void*)elf, sizeof(Elf_Ehdr)) != sizeof(Elf_Ehdr)) {
147 1.2.2.1 bouyer debug_printf(TEXT("read header error\n"));
148 1.2.2.1 bouyer msg_printf(MSG_ERROR, whoami, TEXT("read header error.\n"));
149 1.2.2.1 bouyer goto error_cleanup;
150 1.2.2.1 bouyer }
151 1.2.2.1 bouyer
152 1.2.2.1 bouyer if ((phtbl = (Elf_Phdr *)alloc(sizeof(*phtbl) * elf->e_phnum)) == NULL ||
153 1.2.2.1 bouyer (shtbl = (Elf_Shdr *)alloc(sizeof(*shtbl) * elf->e_shnum)) == NULL) {
154 1.2.2.1 bouyer debug_printf(TEXT("alloc() error\n"));
155 1.2.2.1 bouyer msg_printf(MSG_ERROR, whoami, TEXT("malloc() error.\n"));
156 1.2.2.1 bouyer goto error_cleanup;
157 1.2.2.1 bouyer }
158 1.2.2.1 bouyer
159 1.2.2.1 bouyer if (lseek(fd, elf->e_phoff, SEEK_SET) == -1) {
160 1.2.2.1 bouyer debug_printf(TEXT("seek for program header table error\n"));
161 1.2.2.1 bouyer msg_printf(MSG_ERROR, whoami, TEXT("seek for program header table error.\n"));
162 1.2.2.1 bouyer goto error_cleanup;
163 1.2.2.1 bouyer }
164 1.2.2.1 bouyer if (read(fd, (void *)phtbl, sizeof(Elf_Phdr) * elf->e_phnum)
165 1.2.2.1 bouyer != (int)(sizeof(Elf_Phdr) * elf->e_phnum)) {
166 1.2.2.1 bouyer debug_printf(TEXT("read program header table error\n"));
167 1.2.2.1 bouyer msg_printf(MSG_ERROR, whoami, TEXT("read program header table error.\n"));
168 1.2.2.1 bouyer goto error_cleanup;
169 1.2.2.1 bouyer }
170 1.2.2.1 bouyer
171 1.2.2.1 bouyer if (lseek(fd, elf->e_shoff, SEEK_SET) == -1) {
172 1.2.2.1 bouyer debug_printf(TEXT("seek for segment header table error.\n"));
173 1.2.2.1 bouyer msg_printf(MSG_ERROR, whoami, TEXT("seek for segment header table error.\n"));
174 1.2.2.1 bouyer goto error_cleanup;
175 1.2.2.1 bouyer }
176 1.2.2.1 bouyer if (read(fd, (void *)shtbl, sizeof(Elf_Shdr) * elf->e_shnum)
177 1.2.2.1 bouyer != (int)(sizeof(Elf_Shdr) * elf->e_shnum)) {
178 1.2.2.1 bouyer debug_printf(TEXT("read segment header table error\n"));
179 1.2.2.1 bouyer msg_printf(MSG_ERROR, whoami, TEXT("read segment header table error.\n"));
180 1.2.2.1 bouyer goto error_cleanup;
181 1.2.2.1 bouyer }
182 1.2.2.1 bouyer
183 1.2.2.1 bouyer /*
184 1.2.2.1 bouyer * scan program header table
185 1.2.2.1 bouyer */
186 1.2.2.1 bouyer first = 1;
187 1.2.2.1 bouyer byte_count = 0;
188 1.2.2.1 bouyer progress = 0;
189 1.2.2.1 bouyer for (i = 0; i < elf->e_phnum; i++) {
190 1.2.2.1 bouyer if (phtbl[i].p_type != PT_LOAD) {
191 1.2.2.1 bouyer continue;
192 1.2.2.1 bouyer }
193 1.2.2.1 bouyer
194 1.2.2.1 bouyer if (first || max_addr < (caddr_t)(phtbl[i].p_vaddr + phtbl[i].p_memsz)) {
195 1.2.2.1 bouyer max_addr = (caddr_t)(phtbl[i].p_vaddr + phtbl[i].p_memsz);
196 1.2.2.1 bouyer }
197 1.2.2.1 bouyer if (first || (caddr_t)phtbl[i].p_vaddr < min_addr) {
198 1.2.2.1 bouyer min_addr = (caddr_t)phtbl[i].p_vaddr;
199 1.2.2.1 bouyer }
200 1.2.2.1 bouyer
201 1.2.2.1 bouyer if (load) {
202 1.2.2.1 bouyer if (lseek(fd, phtbl[i].p_offset, SEEK_SET) == -1) {
203 1.2.2.1 bouyer debug_printf(TEXT("seek for segment error\n"));
204 1.2.2.1 bouyer msg_printf(MSG_ERROR, whoami, TEXT("seek for segment error.\n"));
205 1.2.2.1 bouyer goto error_cleanup;
206 1.2.2.1 bouyer }
207 1.2.2.1 bouyer
208 1.2.2.1 bouyer if (vmem_sub(VMEM_LOAD, (void*)fd,
209 1.2.2.1 bouyer (caddr_t)phtbl[i].p_vaddr,
210 1.2.2.1 bouyer phtbl[i].p_filesz,
211 1.2.2.1 bouyer &byte_count) != 0) {
212 1.2.2.1 bouyer goto error_cleanup;
213 1.2.2.1 bouyer }
214 1.2.2.1 bouyer if (vmem_sub(VMEM_CLEAR, NULL,
215 1.2.2.1 bouyer (caddr_t)phtbl[i].p_vaddr + phtbl[i].p_filesz,
216 1.2.2.1 bouyer phtbl[i].p_memsz - phtbl[i].p_filesz,
217 1.2.2.1 bouyer &byte_count) != 0) {
218 1.2.2.1 bouyer goto error_cleanup;
219 1.2.2.1 bouyer }
220 1.2.2.1 bouyer } else {
221 1.2.2.1 bouyer byte_count += phtbl[i].p_memsz;
222 1.2.2.1 bouyer }
223 1.2.2.1 bouyer
224 1.2.2.1 bouyer first = 0;
225 1.2.2.1 bouyer }
226 1.2.2.1 bouyer
227 1.2.2.1 bouyer if (first) {
228 1.2.2.1 bouyer debug_printf(TEXT("can't find loadable segment\n"));
229 1.2.2.1 bouyer msg_printf(MSG_ERROR, whoami, TEXT("can't find loadable segment\n"));
230 1.2.2.1 bouyer goto error_cleanup;
231 1.2.2.1 bouyer }
232 1.2.2.1 bouyer total_bytes = byte_count;
233 1.2.2.1 bouyer
234 1.2.2.1 bouyer debug_printf(TEXT("entry=%x addr=%x-%x\n"),
235 1.2.2.1 bouyer elf->e_entry, min_addr, max_addr);
236 1.2.2.1 bouyer
237 1.2.2.1 bouyer #ifdef LOAD_DEBUG_INFO
238 1.2.2.1 bouyer if (pref.load_debug_info) {
239 1.2.2.1 bouyer /*
240 1.2.2.1 bouyer * scan section header table
241 1.2.2.1 bouyer * to search for debuging infomation
242 1.2.2.1 bouyer */
243 1.2.2.1 bouyer sh_symidx = -1;
244 1.2.2.1 bouyer sh_stridx = -1;
245 1.2.2.1 bouyer for (i = 0; i < elf->e_shnum; i++) {
246 1.2.2.1 bouyer if (shtbl[i].sh_type == SHT_SYMTAB) {
247 1.2.2.1 bouyer sh_symidx = i;
248 1.2.2.1 bouyer }
249 1.2.2.1 bouyer if ((shtbl[i].sh_type == SHT_STRTAB)
250 1.2.2.1 bouyer && (shtbl[i].sh_size >= 0x4000)) {
251 1.2.2.1 bouyer sh_stridx = i;
252 1.2.2.1 bouyer }
253 1.2.2.1 bouyer }
254 1.2.2.1 bouyer if (sh_symidx == -1 || sh_stridx == -1) {
255 1.2.2.1 bouyer debug_printf(TEXT("debuging infomation not found\n"));
256 1.2.2.1 bouyer } else
257 1.2.2.1 bouyer if (load) {
258 1.2.2.1 bouyer Elf_Ehdr dbg_eh;
259 1.2.2.1 bouyer Elf_Shdr dbg_sh[2];
260 1.2.2.1 bouyer memset(&dbg_eh, 0, sizeof(Elf_Ehdr));
261 1.2.2.1 bouyer memset(dbg_sh, 0, sizeof(Elf_Shdr) * 2);
262 1.2.2.1 bouyer
263 1.2.2.1 bouyer memcpy(dbg_eh.e_ident, elf->e_ident,
264 1.2.2.1 bouyer sizeof(elf->e_ident));
265 1.2.2.1 bouyer dbg_eh.e_machine = elf->e_machine;
266 1.2.2.1 bouyer dbg_eh.e_version = elf->e_version;
267 1.2.2.1 bouyer dbg_eh.e_entry = 0;
268 1.2.2.1 bouyer dbg_eh.e_phoff = 0;
269 1.2.2.1 bouyer dbg_eh.e_shoff = sizeof(Elf_Ehdr);
270 1.2.2.1 bouyer dbg_eh.e_flags = elf->e_flags;
271 1.2.2.1 bouyer dbg_eh.e_ehsize = sizeof(Elf_Ehdr);
272 1.2.2.1 bouyer dbg_eh.e_phentsize = 0;
273 1.2.2.1 bouyer dbg_eh.e_phnum = 0;
274 1.2.2.1 bouyer dbg_eh.e_shentsize = sizeof(Elf_Shdr);
275 1.2.2.1 bouyer dbg_eh.e_shnum = 2;
276 1.2.2.1 bouyer dbg_eh.e_shstrndx = 0; /* ??? */
277 1.2.2.1 bouyer
278 1.2.2.1 bouyer /*
279 1.2.2.1 bouyer * XXX, pass debug info size in e_entry.
280 1.2.2.1 bouyer */
281 1.2.2.1 bouyer dbg_eh.e_entry = ROUNDUP(dbg_hdr_size +
282 1.2.2.1 bouyer shtbl[sh_symidx].sh_size +
283 1.2.2.1 bouyer shtbl[sh_stridx].sh_size,
284 1.2.2.1 bouyer DEBUG_INFO_ALIGN);
285 1.2.2.1 bouyer
286 1.2.2.1 bouyer if (vmem_sub(VMEM_COPY, (void*)&dbg_eh,
287 1.2.2.1 bouyer max_addr,
288 1.2.2.1 bouyer sizeof(Elf_Ehdr),
289 1.2.2.1 bouyer &byte_count) != 0) {
290 1.2.2.1 bouyer goto error_cleanup;
291 1.2.2.1 bouyer }
292 1.2.2.1 bouyer
293 1.2.2.1 bouyer dbg_sh[0].sh_type = shtbl[sh_symidx].sh_type;
294 1.2.2.1 bouyer dbg_sh[0].sh_offset = dbg_hdr_size;
295 1.2.2.1 bouyer dbg_sh[0].sh_size = shtbl[sh_symidx].sh_size;
296 1.2.2.1 bouyer dbg_sh[0].sh_addralign = shtbl[sh_symidx].sh_addralign;
297 1.2.2.1 bouyer dbg_sh[1].sh_type = shtbl[sh_stridx].sh_type;
298 1.2.2.1 bouyer dbg_sh[1].sh_offset = dbg_hdr_size + shtbl[sh_symidx].sh_size;
299 1.2.2.1 bouyer dbg_sh[1].sh_size = shtbl[sh_stridx].sh_size;
300 1.2.2.1 bouyer dbg_sh[1].sh_addralign = shtbl[sh_stridx].sh_addralign;
301 1.2.2.1 bouyer if (vmem_sub(VMEM_COPY, (void*)dbg_sh,
302 1.2.2.1 bouyer max_addr + sizeof(Elf_Ehdr),
303 1.2.2.1 bouyer sizeof(Elf_Shdr) * 2,
304 1.2.2.1 bouyer &byte_count) != 0) {
305 1.2.2.1 bouyer goto error_cleanup;
306 1.2.2.1 bouyer }
307 1.2.2.1 bouyer
308 1.2.2.1 bouyer if (lseek(fd, shtbl[sh_symidx].sh_offset, SEEK_SET) == -1) {
309 1.2.2.1 bouyer debug_printf(TEXT("seek for debug symbol error\n"));
310 1.2.2.1 bouyer msg_printf(MSG_ERROR, whoami,
311 1.2.2.1 bouyer TEXT("seek for segment error.\n"));
312 1.2.2.1 bouyer goto error_cleanup;
313 1.2.2.1 bouyer }
314 1.2.2.1 bouyer if (vmem_sub(VMEM_LOAD, (void*)fd,
315 1.2.2.1 bouyer max_addr + dbg_hdr_size,
316 1.2.2.1 bouyer shtbl[sh_symidx].sh_size,
317 1.2.2.1 bouyer &byte_count) != 0) {
318 1.2.2.1 bouyer goto error_cleanup;
319 1.2.2.1 bouyer }
320 1.2.2.1 bouyer
321 1.2.2.1 bouyer if (lseek(fd, shtbl[sh_stridx].sh_offset, SEEK_SET) == -1) {
322 1.2.2.1 bouyer debug_printf(TEXT("seek for string table error\n"));
323 1.2.2.1 bouyer msg_printf(MSG_ERROR, whoami,
324 1.2.2.1 bouyer TEXT("seek for segment error.\n"));
325 1.2.2.1 bouyer goto error_cleanup;
326 1.2.2.1 bouyer }
327 1.2.2.1 bouyer if (vmem_sub(VMEM_LOAD, (void*)fd,
328 1.2.2.1 bouyer max_addr + dbg_hdr_size + shtbl[sh_symidx].sh_size,
329 1.2.2.1 bouyer shtbl[sh_stridx].sh_size,
330 1.2.2.1 bouyer &byte_count) != 0) {
331 1.2.2.1 bouyer goto error_cleanup;
332 1.2.2.1 bouyer }
333 1.2.2.1 bouyer } else {
334 1.2.2.1 bouyer /*
335 1.2.2.1 bouyer * make space for debuging infomation
336 1.2.2.1 bouyer */
337 1.2.2.1 bouyer int dbg_info_size = ROUNDUP(dbg_hdr_size +
338 1.2.2.1 bouyer shtbl[sh_symidx].sh_size +
339 1.2.2.1 bouyer shtbl[sh_stridx].sh_size,
340 1.2.2.1 bouyer DEBUG_INFO_ALIGN);
341 1.2.2.1 bouyer debug_printf(TEXT("%x bytes debug infomation\n"),
342 1.2.2.1 bouyer dbg_info_size);
343 1.2.2.1 bouyer max_addr += dbg_info_size;
344 1.2.2.1 bouyer total_bytes += dbg_info_size;
345 1.2.2.1 bouyer }
346 1.2.2.1 bouyer }
347 1.2.2.1 bouyer #endif /* LOAD_DEBUG_INFO */
348 1.2.2.1 bouyer
349 1.2.2.1 bouyer if (phtbl) free(phtbl, sizeof(*phtbl) * elf->e_phnum);
350 1.2.2.1 bouyer if (shtbl) free(shtbl, sizeof(*shtbl) * elf->e_shnum);
351 1.2.2.1 bouyer
352 1.2.2.1 bouyer if (start) *start = min_addr;
353 1.2.2.1 bouyer if (end) *end = max_addr;
354 1.2.2.1 bouyer if (entry) *entry = (caddr_t)elf->e_entry;
355 1.2.2.1 bouyer return (0);
356 1.2.2.1 bouyer
357 1.2.2.1 bouyer error_cleanup:
358 1.2.2.1 bouyer if (phtbl) free(phtbl, sizeof(*phtbl) * elf->e_phnum);
359 1.2.2.1 bouyer if (shtbl) free(shtbl, sizeof(*shtbl) * elf->e_shnum);
360 1.2.2.1 bouyer return (-1);
361 1.2.2.1 bouyer }
362