xref: /haiku/src/system/runtime_loader/elf_load_image.cpp (revision 47c05920fde47c2618efccd24bd82f1e79cdf05a)
1 /*
2  * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2003-2012, Axel Dörfler, axeld@pinc-software.de.
4  * Distributed under the terms of the MIT License.
5  *
6  * Copyright 2002, Manuel J. Petit. All rights reserved.
7  * Copyright 2001, Travis Geiselbrecht. All rights reserved.
8  * Distributed under the terms of the NewOS License.
9  */
10 
11 #include "elf_load_image.h"
12 
13 #include <stdio.h>
14 #include <string.h>
15 
16 #include <syscalls.h>
17 
18 #include "add_ons.h"
19 #include "elf_haiku_version.h"
20 #include "elf_symbol_lookup.h"
21 #include "elf_tls.h"
22 #include "elf_versioning.h"
23 #include "images.h"
24 #include "runtime_loader_private.h"
25 
26 
27 static const char* sSearchPathSubDir = NULL;
28 
29 
30 static const char*
31 get_program_path()
32 {
33 	return gProgramImage != NULL ? gProgramImage->path : NULL;
34 }
35 
36 
37 static int32
38 count_regions(const char* imagePath, char const* buff, int phnum, int phentsize)
39 {
40 	elf_phdr* pheaders;
41 	int32 count = 0;
42 	int i;
43 
44 	for (i = 0; i < phnum; i++) {
45 		pheaders = (elf_phdr*)(buff + i * phentsize);
46 
47 		switch (pheaders->p_type) {
48 			case PT_NULL:
49 				// NOP header
50 				break;
51 			case PT_LOAD:
52 				count += 1;
53 				if (pheaders->p_memsz != pheaders->p_filesz) {
54 					addr_t A = TO_PAGE_SIZE(pheaders->p_vaddr
55 						+ pheaders->p_memsz);
56 					addr_t B = TO_PAGE_SIZE(pheaders->p_vaddr
57 						+ pheaders->p_filesz);
58 
59 					if (A != B)
60 						count += 1;
61 				}
62 				break;
63 			case PT_DYNAMIC:
64 				// will be handled at some other place
65 				break;
66 			case PT_INTERP:
67 				// should check here for appropriate interpreter
68 				break;
69 			case PT_NOTE:
70 				// unsupported
71 				break;
72 			case PT_SHLIB:
73 				// undefined semantics
74 				break;
75 			case PT_PHDR:
76 				// we don't use it
77 				break;
78 			case PT_EH_FRAME:
79 			case PT_RELRO:
80 				// not implemented yet, but can be ignored
81 				break;
82 			case PT_STACK:
83 				// we don't use it
84 				break;
85 			case PT_TLS:
86 				// will be handled at some other place
87 				break;
88 			case PT_ARM_UNWIND:
89 				// will be handled in libgcc_s.so.1
90 				break;
91 			case PT_RISCV_ATTRIBUTES:
92 				// TODO: check ABI compatibility attributes
93 				break;
94 			default:
95 				FATAL("%s: Unhandled pheader type in count 0x%" B_PRIx32 "\n",
96 					imagePath, pheaders->p_type);
97 				break;
98 		}
99 	}
100 
101 	return count;
102 }
103 
104 
105 static status_t
106 parse_program_headers(image_t* image, char* buff, int phnum, int phentsize)
107 {
108 	elf_phdr* pheader;
109 	int regcount;
110 	int i;
111 
112 	image->dso_tls_id = unsigned(-1);
113 
114 	regcount = 0;
115 	for (i = 0; i < phnum; i++) {
116 		pheader = (elf_phdr*)(buff + i * phentsize);
117 
118 		switch (pheader->p_type) {
119 			case PT_NULL:
120 				/* NOP header */
121 				break;
122 			case PT_LOAD:
123 				if (pheader->p_memsz == pheader->p_filesz) {
124 					/*
125 					 * everything in one area
126 					 */
127 					image->regions[regcount].start = pheader->p_vaddr;
128 					image->regions[regcount].size = pheader->p_memsz;
129 					image->regions[regcount].vmstart
130 						= PAGE_BASE(pheader->p_vaddr);
131 					image->regions[regcount].vmsize
132 						= TO_PAGE_SIZE(pheader->p_memsz
133 							+ PAGE_OFFSET(pheader->p_vaddr));
134 					image->regions[regcount].fdstart = pheader->p_offset;
135 					image->regions[regcount].fdsize = pheader->p_filesz;
136 					image->regions[regcount].delta = 0;
137 					image->regions[regcount].flags = 0;
138 					if (pheader->p_flags & PF_WRITE) {
139 						// this is a writable segment
140 						image->regions[regcount].flags |= RFLAG_RW;
141 					}
142 				} else {
143 					/*
144 					 * may require splitting
145 					 */
146 					addr_t A = TO_PAGE_SIZE(pheader->p_vaddr
147 						+ pheader->p_memsz);
148 					addr_t B = TO_PAGE_SIZE(pheader->p_vaddr
149 						+ pheader->p_filesz);
150 
151 					image->regions[regcount].start = pheader->p_vaddr;
152 					image->regions[regcount].size = pheader->p_filesz;
153 					image->regions[regcount].vmstart
154 						= PAGE_BASE(pheader->p_vaddr);
155 					image->regions[regcount].vmsize
156 						= TO_PAGE_SIZE(pheader->p_filesz
157 							+ PAGE_OFFSET(pheader->p_vaddr));
158 					image->regions[regcount].fdstart = pheader->p_offset;
159 					image->regions[regcount].fdsize = pheader->p_filesz;
160 					image->regions[regcount].delta = 0;
161 					image->regions[regcount].flags = 0;
162 					if (pheader->p_flags & PF_WRITE) {
163 						// this is a writable segment
164 						image->regions[regcount].flags |= RFLAG_RW;
165 					}
166 
167 					if (A != B) {
168 						/*
169 						 * yeah, it requires splitting
170 						 */
171 						regcount += 1;
172 						image->regions[regcount].start = pheader->p_vaddr;
173 						image->regions[regcount].size
174 							= pheader->p_memsz - pheader->p_filesz;
175 						image->regions[regcount].vmstart
176 							= image->regions[regcount-1].vmstart
177 								+ image->regions[regcount-1].vmsize;
178 						image->regions[regcount].vmsize
179 							= TO_PAGE_SIZE(pheader->p_memsz
180 									+ PAGE_OFFSET(pheader->p_vaddr))
181 								- image->regions[regcount-1].vmsize;
182 						image->regions[regcount].fdstart = 0;
183 						image->regions[regcount].fdsize = 0;
184 						image->regions[regcount].delta = 0;
185 						image->regions[regcount].flags = RFLAG_ANON;
186 						if (pheader->p_flags & PF_WRITE) {
187 							// this is a writable segment
188 							image->regions[regcount].flags |= RFLAG_RW;
189 						}
190 					}
191 				}
192 				regcount += 1;
193 				break;
194 			case PT_DYNAMIC:
195 				image->dynamic_ptr = pheader->p_vaddr;
196 				break;
197 			case PT_INTERP:
198 				// should check here for appropiate interpreter
199 				break;
200 			case PT_NOTE:
201 				// unsupported
202 				break;
203 			case PT_SHLIB:
204 				// undefined semantics
205 				break;
206 			case PT_PHDR:
207 				// we don't use it
208 				break;
209 			case PT_EH_FRAME:
210 			case PT_RELRO:
211 				// not implemented yet, but can be ignored
212 				break;
213 			case PT_STACK:
214 				// we don't use it
215 				break;
216 			case PT_TLS:
217 				image->dso_tls_id
218 					= TLSBlockTemplates::Get().Register(
219 						TLSBlockTemplate((void*)pheader->p_vaddr,
220 							pheader->p_filesz, pheader->p_memsz));
221 				break;
222 			case PT_ARM_UNWIND:
223 				// will be handled in libgcc_s.so.1
224 				break;
225 			case PT_RISCV_ATTRIBUTES:
226 				// TODO: check ABI compatibility attributes
227 				break;
228 			default:
229 				FATAL("%s: Unhandled pheader type in parse 0x%" B_PRIx32 "\n",
230 					image->path, pheader->p_type);
231 				return B_BAD_DATA;
232 		}
233 	}
234 
235 	return B_OK;
236 }
237 
238 
239 static bool
240 assert_dynamic_loadable(image_t* image)
241 {
242 	uint32 i;
243 
244 	if (!image->dynamic_ptr)
245 		return true;
246 
247 	for (i = 0; i < image->num_regions; i++) {
248 		if (image->dynamic_ptr >= image->regions[i].start
249 			&& image->dynamic_ptr
250 				< image->regions[i].start + image->regions[i].size) {
251 			return true;
252 		}
253 	}
254 
255 	return false;
256 }
257 
258 
259 static bool
260 parse_dynamic_segment(image_t* image)
261 {
262 	elf_dyn* d;
263 	int i;
264 	int sonameOffset = -1;
265 
266 	image->symhash = 0;
267 	image->syms = 0;
268 	image->strtab = 0;
269 
270 	d = (elf_dyn*)image->dynamic_ptr;
271 	if (!d)
272 		return true;
273 
274 	for (i = 0; d[i].d_tag != DT_NULL; i++) {
275 		switch (d[i].d_tag) {
276 			case DT_NEEDED:
277 				image->num_needed += 1;
278 				break;
279 			case DT_HASH:
280 				image->symhash
281 					= (uint32*)(d[i].d_un.d_ptr + image->regions[0].delta);
282 				break;
283 			case DT_STRTAB:
284 				image->strtab
285 					= (char*)(d[i].d_un.d_ptr + image->regions[0].delta);
286 				break;
287 			case DT_SYMTAB:
288 				image->syms = (elf_sym*)
289 					(d[i].d_un.d_ptr + image->regions[0].delta);
290 				break;
291 			case DT_REL:
292 				image->rel = (elf_rel*)
293 					(d[i].d_un.d_ptr + image->regions[0].delta);
294 				break;
295 			case DT_RELSZ:
296 				image->rel_len = d[i].d_un.d_val;
297 				break;
298 			case DT_RELA:
299 				image->rela = (elf_rela*)
300 					(d[i].d_un.d_ptr + image->regions[0].delta);
301 				break;
302 			case DT_RELASZ:
303 				image->rela_len = d[i].d_un.d_val;
304 				break;
305 			case DT_JMPREL:
306 				// procedure linkage table relocations
307 				image->pltrel = (elf_rel*)
308 					(d[i].d_un.d_ptr + image->regions[0].delta);
309 				break;
310 			case DT_PLTRELSZ:
311 				image->pltrel_len = d[i].d_un.d_val;
312 				break;
313 			case DT_INIT:
314 				image->init_routine
315 					= (d[i].d_un.d_ptr + image->regions[0].delta);
316 				break;
317 			case DT_FINI:
318 				image->term_routine
319 					= (d[i].d_un.d_ptr + image->regions[0].delta);
320 				break;
321 			case DT_SONAME:
322 				sonameOffset = d[i].d_un.d_val;
323 				break;
324 			case DT_VERSYM:
325 				image->symbol_versions = (elf_versym*)
326 					(d[i].d_un.d_ptr + image->regions[0].delta);
327 				break;
328 			case DT_VERDEF:
329 				image->version_definitions = (elf_verdef*)
330 					(d[i].d_un.d_ptr + image->regions[0].delta);
331 				break;
332 			case DT_VERDEFNUM:
333 				image->num_version_definitions = d[i].d_un.d_val;
334 				break;
335 			case DT_VERNEED:
336 				image->needed_versions = (elf_verneed*)
337 					(d[i].d_un.d_ptr + image->regions[0].delta);
338 				break;
339 			case DT_VERNEEDNUM:
340 				image->num_needed_versions = d[i].d_un.d_val;
341 				break;
342 			case DT_SYMBOLIC:
343 				image->flags |= RFLAG_SYMBOLIC;
344 				break;
345 			case DT_FLAGS:
346 			{
347 				uint32 flags = d[i].d_un.d_val;
348 				if ((flags & DF_SYMBOLIC) != 0)
349 					image->flags |= RFLAG_SYMBOLIC;
350 				if ((flags & DF_STATIC_TLS) != 0) {
351 					FATAL("Static TLS model is not supported.\n");
352 					return false;
353 				}
354 				break;
355 			}
356 			case DT_INIT_ARRAY:
357 				// array of pointers to initialization functions
358 				image->init_array = (addr_t*)
359 					(d[i].d_un.d_ptr + image->regions[0].delta);
360 				break;
361 			case DT_INIT_ARRAYSZ:
362 				// size in bytes of the array of initialization functions
363 				image->init_array_len = d[i].d_un.d_val;
364 				break;
365 			case DT_PREINIT_ARRAY:
366 				// array of pointers to pre-initialization functions
367 				image->preinit_array = (addr_t*)
368 					(d[i].d_un.d_ptr + image->regions[0].delta);
369 				break;
370 			case DT_PREINIT_ARRAYSZ:
371 				// size in bytes of the array of pre-initialization functions
372 				image->preinit_array_len = d[i].d_un.d_val;
373 				break;
374 			case DT_FINI_ARRAY:
375 				// array of pointers to termination functions
376 				image->term_array = (addr_t*)
377 					(d[i].d_un.d_ptr + image->regions[0].delta);
378 				break;
379 			case DT_FINI_ARRAYSZ:
380 				// size in bytes of the array of termination functions
381 				image->term_array_len = d[i].d_un.d_val;
382 				break;
383 			default:
384 				continue;
385 
386 			// TODO: Implement:
387 			// DT_RELENT: The size of a DT_REL entry.
388 			// DT_RELAENT: The size of a DT_RELA entry.
389 			// DT_SYMENT: The size of a symbol table entry.
390 			// DT_PLTREL: The type of the PLT relocation entries (DT_JMPREL).
391 			// DT_BIND_NOW/DF_BIND_NOW: No lazy binding allowed.
392 			// DT_TEXTREL/DF_TEXTREL: Indicates whether text relocations are
393 			//		required (for optimization purposes only).
394 		}
395 	}
396 
397 	// lets make sure we found all the required sections
398 	if (!image->symhash || !image->syms || !image->strtab)
399 		return false;
400 
401 	if (sonameOffset >= 0)
402 		strlcpy(image->name, STRING(image, sonameOffset), sizeof(image->name));
403 
404 	return true;
405 }
406 
407 
408 // #pragma mark -
409 
410 
411 status_t
412 parse_elf_header(elf_ehdr* eheader, int32* _pheaderSize,
413 	int32* _sheaderSize)
414 {
415 	if (memcmp(eheader->e_ident, ELFMAG, 4) != 0)
416 		return B_NOT_AN_EXECUTABLE;
417 
418 	if (eheader->e_ident[4] != ELF_CLASS)
419 		return B_NOT_AN_EXECUTABLE;
420 
421 	if (eheader->e_phoff == 0)
422 		return B_NOT_AN_EXECUTABLE;
423 
424 	if (eheader->e_phentsize < sizeof(elf_phdr))
425 		return B_NOT_AN_EXECUTABLE;
426 
427 	*_pheaderSize = eheader->e_phentsize * eheader->e_phnum;
428 	*_sheaderSize = eheader->e_shentsize * eheader->e_shnum;
429 
430 	if (*_pheaderSize <= 0)
431 		return B_NOT_AN_EXECUTABLE;
432 
433 	return B_OK;
434 }
435 
436 
437 #if defined(_COMPAT_MODE)
438 #if defined(__x86_64__)
439 status_t
440 parse_elf32_header(Elf32_Ehdr* eheader, int32* _pheaderSize,
441 	int32* _sheaderSize)
442 {
443 	if (memcmp(eheader->e_ident, ELFMAG, 4) != 0)
444 		return B_NOT_AN_EXECUTABLE;
445 
446 	if (eheader->e_ident[4] != ELFCLASS32)
447 		return B_NOT_AN_EXECUTABLE;
448 
449 	if (eheader->e_phoff == 0)
450 		return B_NOT_AN_EXECUTABLE;
451 
452 	if (eheader->e_phentsize < sizeof(Elf32_Phdr))
453 		return B_NOT_AN_EXECUTABLE;
454 
455 	*_pheaderSize = eheader->e_phentsize * eheader->e_phnum;
456 	*_sheaderSize = eheader->e_shentsize * eheader->e_shnum;
457 
458 	if (*_pheaderSize <= 0)
459 		return B_NOT_AN_EXECUTABLE;
460 
461 	return B_OK;
462 }
463 #else
464 status_t
465 parse_elf64_header(Elf64_Ehdr* eheader, int32* _pheaderSize,
466 	int32* _sheaderSize)
467 {
468 	if (memcmp(eheader->e_ident, ELFMAG, 4) != 0)
469 		return B_NOT_AN_EXECUTABLE;
470 
471 	if (eheader->e_ident[4] != ELFCLASS64)
472 		return B_NOT_AN_EXECUTABLE;
473 
474 	if (eheader->e_phoff == 0)
475 		return B_NOT_AN_EXECUTABLE;
476 
477 	if (eheader->e_phentsize < sizeof(Elf64_Phdr))
478 		return B_NOT_AN_EXECUTABLE;
479 
480 	*_pheaderSize = eheader->e_phentsize * eheader->e_phnum;
481 	*_sheaderSize = eheader->e_shentsize * eheader->e_shnum;
482 
483 	if (*_pheaderSize <= 0)
484 		return B_NOT_AN_EXECUTABLE;
485 
486 	return B_OK;
487 }
488 #endif	// __x86_64__
489 #endif	// _COMPAT_MODE
490 
491 
492 status_t
493 load_image(char const* name, image_type type, const char* rpath, const char* runpath,
494 	const char* requestingObjectPath, image_t** _image)
495 {
496 	int32 pheaderSize, sheaderSize;
497 	char path[PATH_MAX];
498 	ssize_t length;
499 	char pheaderBuffer[4096];
500 	int32 numRegions;
501 	image_t* found;
502 	image_t* image;
503 	status_t status;
504 	int fd;
505 
506 	elf_ehdr eheader;
507 
508 	// Have we already loaded that image? Don't check for add-ons -- we always
509 	// reload them.
510 	if (type != B_ADD_ON_IMAGE) {
511 		found = find_loaded_image_by_name(name, APP_OR_LIBRARY_TYPE);
512 
513 		if (found == NULL && type != B_APP_IMAGE && gProgramImage != NULL) {
514 			// Special case for add-ons that link against the application
515 			// executable, with the executable not having a soname set.
516 			if (const char* lastSlash = strrchr(name, '/')) {
517 				if (strcmp(gProgramImage->name, lastSlash + 1) == 0)
518 					found = gProgramImage;
519 			}
520 		}
521 
522 		if (found) {
523 			atomic_add(&found->ref_count, 1);
524 			*_image = found;
525 			KTRACE("rld: load_container(\"%s\", type: %d, %s: \"%s\") "
526 				"already loaded", name, type,
527 				runpath != NULL ? "runpath" : "rpath", runpath != NULL ? runpath : rpath);
528 			return B_OK;
529 		}
530 	}
531 
532 	KTRACE("rld: load_container(\"%s\", type: %d, %s: \"%s\")", name, type,
533 		runpath != NULL ? "runpath" : "rpath", runpath != NULL ? runpath : rpath);
534 
535 	strlcpy(path, name, sizeof(path));
536 
537 	// find and open the file
538 	fd = open_executable(path, type, rpath, runpath, get_program_path(),
539 		requestingObjectPath, sSearchPathSubDir);
540 	if (fd < 0) {
541 		FATAL("Cannot open file %s (needed by %s): %s\n", name, requestingObjectPath, strerror(fd));
542 		KTRACE("rld: load_container(\"%s\"): failed to open file", name);
543 		return fd;
544 	}
545 
546 	// normalize the image path
547 	status = _kern_normalize_path(path, true, path);
548 	if (status != B_OK)
549 		goto err1;
550 
551 	// Test again if this image has been registered already - this time,
552 	// we can check the full path, not just its name as noted.
553 	// You could end up loading an image twice with symbolic links, else.
554 	if (type != B_ADD_ON_IMAGE) {
555 		found = find_loaded_image_by_name(path, APP_OR_LIBRARY_TYPE);
556 		if (found) {
557 			atomic_add(&found->ref_count, 1);
558 			*_image = found;
559 			_kern_close(fd);
560 			KTRACE("rld: load_container(\"%s\"): already loaded after all",
561 				name);
562 			return B_OK;
563 		}
564 	}
565 
566 	length = _kern_read(fd, 0, &eheader, sizeof(eheader));
567 	if (length != sizeof(eheader)) {
568 		status = B_NOT_AN_EXECUTABLE;
569 		FATAL("%s: Troubles reading ELF header\n", path);
570 		goto err1;
571 	}
572 
573 	status = parse_elf_header(&eheader, &pheaderSize, &sheaderSize);
574 	if (status < B_OK) {
575 		FATAL("%s: Incorrect ELF header\n", path);
576 		goto err1;
577 	}
578 
579 	// ToDo: what to do about this restriction??
580 	if (pheaderSize > (int)sizeof(pheaderBuffer)) {
581 		FATAL("%s: Cannot handle program headers bigger than %lu\n",
582 			path, sizeof(pheaderBuffer));
583 		status = B_UNSUPPORTED;
584 		goto err1;
585 	}
586 
587 	length = _kern_read(fd, eheader.e_phoff, pheaderBuffer, pheaderSize);
588 	if (length != pheaderSize) {
589 		FATAL("%s: Could not read program headers: %s\n", path,
590 			strerror(length));
591 		status = B_BAD_DATA;
592 		goto err1;
593 	}
594 
595 	numRegions = count_regions(path, pheaderBuffer, eheader.e_phnum,
596 		eheader.e_phentsize);
597 	if (numRegions <= 0) {
598 		FATAL("%s: Troubles parsing Program headers, numRegions = %" B_PRId32
599 			"\n", path, numRegions);
600 		status = B_BAD_DATA;
601 		goto err1;
602 	}
603 
604 	image = create_image(name, path, numRegions);
605 	if (image == NULL) {
606 		FATAL("%s: Failed to allocate image_t object\n", path);
607 		status = B_NO_MEMORY;
608 		goto err1;
609 	}
610 
611 	status = parse_program_headers(image, pheaderBuffer, eheader.e_phnum,
612 		eheader.e_phentsize);
613 	if (status < B_OK)
614 		goto err2;
615 
616 	if (!assert_dynamic_loadable(image)) {
617 		FATAL("%s: Dynamic segment must be loadable (implementation "
618 			"restriction)\n", image->path);
619 		status = B_UNSUPPORTED;
620 		goto err2;
621 	}
622 
623 	status = map_image(fd, path, image, eheader.e_type == ET_EXEC);
624 	if (status < B_OK) {
625 		FATAL("%s: Could not map image: %s\n", image->path, strerror(status));
626 		status = B_ERROR;
627 		goto err2;
628 	}
629 
630 	if (!parse_dynamic_segment(image)) {
631 		FATAL("%s: Troubles handling dynamic section\n", image->path);
632 		status = B_BAD_DATA;
633 		goto err3;
634 	}
635 
636 	if (eheader.e_entry != 0)
637 		image->entry_point = eheader.e_entry + image->regions[0].delta;
638 
639 	analyze_image_haiku_version_and_abi(fd, image, eheader, sheaderSize,
640 		pheaderBuffer, sizeof(pheaderBuffer));
641 
642 	// If sSearchPathSubDir is unset (meaning, this is the first image we're
643 	// loading) we init the search path subdir if the compiler version doesn't
644 	// match ours.
645 	if (sSearchPathSubDir == NULL) {
646 		#if __GNUC__ == 2 || (defined(_COMPAT_MODE) && !defined(__x86_64__))
647 			if ((image->abi & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_4)
648 				sSearchPathSubDir = "x86";
649 		#endif
650 		#if __GNUC__ >= 4 || (defined(_COMPAT_MODE) && !defined(__x86_64__))
651 			if ((image->abi & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_2)
652 				sSearchPathSubDir = "x86_gcc2";
653 		#endif
654 	}
655 
656 	set_abi_api_version(image->abi, image->api_version);
657 
658 	// init gcc version dependent image flags
659 	// symbol resolution strategy
660 	if (image->abi == B_HAIKU_ABI_GCC_2_ANCIENT)
661 		image->find_undefined_symbol = find_undefined_symbol_beos;
662 
663 	// init version infos
664 	status = init_image_version_infos(image);
665 
666 	image->type = type;
667 	register_image(image, fd, path);
668 	image_event(image, IMAGE_EVENT_LOADED);
669 
670 	_kern_close(fd);
671 
672 	enqueue_loaded_image(image);
673 
674 	*_image = image;
675 
676 	KTRACE("rld: load_container(\"%s\"): done: id: %" B_PRId32 " (ABI: %#"
677 		B_PRIx32 ")", name, image->id, image->abi);
678 
679 	return B_OK;
680 
681 err3:
682 	unmap_image(image);
683 err2:
684 	delete_image_struct(image);
685 err1:
686 	_kern_close(fd);
687 
688 	KTRACE("rld: load_container(\"%s\"): failed: %s", name,
689 		strerror(status));
690 
691 	return status;
692 }
693