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.
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.
11 #include "elf_load_image.h"
19 #include "elf_haiku_version.h"
20 #include "elf_symbol_lookup.h"
22 #include "elf_versioning.h"
24 #include "runtime_loader_private.h"
27 static const char* sSearchPathSubDir
= NULL
;
33 return gProgramImage
!= NULL
? gProgramImage
->path
: NULL
;
38 count_regions(const char* imagePath
, char const* buff
, int phnum
, int phentsize
)
44 for (i
= 0; i
< phnum
; i
++) {
45 pheaders
= (elf_phdr
*)(buff
+ i
* phentsize
);
47 switch (pheaders
->p_type
) {
53 if (pheaders
->p_memsz
!= pheaders
->p_filesz
) {
54 addr_t A
= TO_PAGE_SIZE(pheaders
->p_vaddr
56 addr_t B
= TO_PAGE_SIZE(pheaders
->p_vaddr
57 + pheaders
->p_filesz
);
64 // will be handled at some other place
67 // should check here for appropriate interpreter
73 // undefined semantics
79 // not implemented yet, but can be ignored
85 // will be handled at some other place
88 FATAL("%s: Unhandled pheader type in count 0x%" B_PRIx32
"\n",
89 imagePath
, pheaders
->p_type
);
99 parse_program_headers(image_t
* image
, char* buff
, int phnum
, int phentsize
)
105 image
->dso_tls_id
= unsigned(-1);
108 for (i
= 0; i
< phnum
; i
++) {
109 pheader
= (elf_phdr
*)(buff
+ i
* phentsize
);
111 switch (pheader
->p_type
) {
116 if (pheader
->p_memsz
== pheader
->p_filesz
) {
118 * everything in one area
120 image
->regions
[regcount
].start
= pheader
->p_vaddr
;
121 image
->regions
[regcount
].size
= pheader
->p_memsz
;
122 image
->regions
[regcount
].vmstart
123 = PAGE_BASE(pheader
->p_vaddr
);
124 image
->regions
[regcount
].vmsize
125 = TO_PAGE_SIZE(pheader
->p_memsz
126 + PAGE_OFFSET(pheader
->p_vaddr
));
127 image
->regions
[regcount
].fdstart
= pheader
->p_offset
;
128 image
->regions
[regcount
].fdsize
= pheader
->p_filesz
;
129 image
->regions
[regcount
].delta
= 0;
130 image
->regions
[regcount
].flags
= 0;
131 if (pheader
->p_flags
& PF_WRITE
) {
132 // this is a writable segment
133 image
->regions
[regcount
].flags
|= RFLAG_RW
;
137 * may require splitting
139 addr_t A
= TO_PAGE_SIZE(pheader
->p_vaddr
141 addr_t B
= TO_PAGE_SIZE(pheader
->p_vaddr
142 + pheader
->p_filesz
);
144 image
->regions
[regcount
].start
= pheader
->p_vaddr
;
145 image
->regions
[regcount
].size
= pheader
->p_filesz
;
146 image
->regions
[regcount
].vmstart
147 = PAGE_BASE(pheader
->p_vaddr
);
148 image
->regions
[regcount
].vmsize
149 = TO_PAGE_SIZE(pheader
->p_filesz
150 + PAGE_OFFSET(pheader
->p_vaddr
));
151 image
->regions
[regcount
].fdstart
= pheader
->p_offset
;
152 image
->regions
[regcount
].fdsize
= pheader
->p_filesz
;
153 image
->regions
[regcount
].delta
= 0;
154 image
->regions
[regcount
].flags
= 0;
155 if (pheader
->p_flags
& PF_WRITE
) {
156 // this is a writable segment
157 image
->regions
[regcount
].flags
|= RFLAG_RW
;
162 * yeah, it requires splitting
165 image
->regions
[regcount
].start
= pheader
->p_vaddr
;
166 image
->regions
[regcount
].size
167 = pheader
->p_memsz
- pheader
->p_filesz
;
168 image
->regions
[regcount
].vmstart
169 = image
->regions
[regcount
-1].vmstart
170 + image
->regions
[regcount
-1].vmsize
;
171 image
->regions
[regcount
].vmsize
172 = TO_PAGE_SIZE(pheader
->p_memsz
173 + PAGE_OFFSET(pheader
->p_vaddr
))
174 - image
->regions
[regcount
-1].vmsize
;
175 image
->regions
[regcount
].fdstart
= 0;
176 image
->regions
[regcount
].fdsize
= 0;
177 image
->regions
[regcount
].delta
= 0;
178 image
->regions
[regcount
].flags
= RFLAG_ANON
;
179 if (pheader
->p_flags
& PF_WRITE
) {
180 // this is a writable segment
181 image
->regions
[regcount
].flags
|= RFLAG_RW
;
188 image
->dynamic_ptr
= pheader
->p_vaddr
;
191 // should check here for appropiate interpreter
197 // undefined semantics
203 // not implemented yet, but can be ignored
210 = TLSBlockTemplates::Get().Register(
211 TLSBlockTemplate((void*)pheader
->p_vaddr
,
212 pheader
->p_filesz
, pheader
->p_memsz
));
215 FATAL("%s: Unhandled pheader type in parse 0x%" B_PRIx32
"\n",
216 image
->path
, pheader
->p_type
);
226 assert_dynamic_loadable(image_t
* image
)
230 if (!image
->dynamic_ptr
)
233 for (i
= 0; i
< image
->num_regions
; i
++) {
234 if (image
->dynamic_ptr
>= image
->regions
[i
].start
235 && image
->dynamic_ptr
236 < image
->regions
[i
].start
+ image
->regions
[i
].size
) {
246 parse_dynamic_segment(image_t
* image
)
250 int sonameOffset
= -1;
256 d
= (elf_dyn
*)image
->dynamic_ptr
;
260 for (i
= 0; d
[i
].d_tag
!= DT_NULL
; i
++) {
261 switch (d
[i
].d_tag
) {
263 image
->num_needed
+= 1;
267 = (uint32
*)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
271 = (char*)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
274 image
->syms
= (elf_sym
*)
275 (d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
278 image
->rel
= (elf_rel
*)
279 (d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
282 image
->rel_len
= d
[i
].d_un
.d_val
;
285 image
->rela
= (elf_rela
*)
286 (d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
289 image
->rela_len
= d
[i
].d_un
.d_val
;
292 // procedure linkage table relocations
293 image
->pltrel
= (elf_rel
*)
294 (d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
297 image
->pltrel_len
= d
[i
].d_un
.d_val
;
301 = (d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
305 = (d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
308 sonameOffset
= d
[i
].d_un
.d_val
;
311 image
->symbol_versions
= (elf_versym
*)
312 (d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
315 image
->version_definitions
= (elf_verdef
*)
316 (d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
319 image
->num_version_definitions
= d
[i
].d_un
.d_val
;
322 image
->needed_versions
= (elf_verneed
*)
323 (d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
326 image
->num_needed_versions
= d
[i
].d_un
.d_val
;
329 image
->flags
|= RFLAG_SYMBOLIC
;
333 uint32 flags
= d
[i
].d_un
.d_val
;
334 if ((flags
& DF_SYMBOLIC
) != 0)
335 image
->flags
|= RFLAG_SYMBOLIC
;
336 if ((flags
& DF_STATIC_TLS
) != 0) {
337 FATAL("Static TLS model is not supported.\n");
343 // array of pointers to initialization functions
344 image
->init_array
= (addr_t
*)
345 (d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
347 case DT_INIT_ARRAYSZ
:
348 // size in bytes of the array of initialization functions
349 image
->init_array_len
= d
[i
].d_un
.d_val
;
351 case DT_PREINIT_ARRAY
:
352 // array of pointers to pre-initialization functions
353 image
->preinit_array
= (addr_t
*)
354 (d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
356 case DT_PREINIT_ARRAYSZ
:
357 // size in bytes of the array of pre-initialization functions
358 image
->preinit_array_len
= d
[i
].d_un
.d_val
;
361 // array of pointers to termination functions
362 image
->term_array
= (addr_t
*)
363 (d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
365 case DT_FINI_ARRAYSZ
:
366 // size in bytes of the array of termination functions
367 image
->term_array_len
= d
[i
].d_un
.d_val
;
373 // DT_RELENT: The size of a DT_REL entry.
374 // DT_RELAENT: The size of a DT_RELA entry.
375 // DT_SYMENT: The size of a symbol table entry.
376 // DT_PLTREL: The type of the PLT relocation entries (DT_JMPREL).
377 // DT_BIND_NOW/DF_BIND_NOW: No lazy binding allowed.
378 // DT_RUNPATH: Library search path (supersedes DT_RPATH).
379 // DT_TEXTREL/DF_TEXTREL: Indicates whether text relocations are
380 // required (for optimization purposes only).
384 // lets make sure we found all the required sections
385 if (!image
->symhash
|| !image
->syms
|| !image
->strtab
)
388 if (sonameOffset
>= 0)
389 strlcpy(image
->name
, STRING(image
, sonameOffset
), sizeof(image
->name
));
399 parse_elf_header(elf_ehdr
* eheader
, int32
* _pheaderSize
,
402 if (memcmp(eheader
->e_ident
, ELFMAG
, 4) != 0)
403 return B_NOT_AN_EXECUTABLE
;
405 if (eheader
->e_ident
[4] != ELF_CLASS
)
406 return B_NOT_AN_EXECUTABLE
;
408 if (eheader
->e_phoff
== 0)
409 return B_NOT_AN_EXECUTABLE
;
411 if (eheader
->e_phentsize
< sizeof(elf_phdr
))
412 return B_NOT_AN_EXECUTABLE
;
414 *_pheaderSize
= eheader
->e_phentsize
* eheader
->e_phnum
;
415 *_sheaderSize
= eheader
->e_shentsize
* eheader
->e_shnum
;
417 if (*_pheaderSize
<= 0 || *_sheaderSize
<= 0)
418 return B_NOT_AN_EXECUTABLE
;
425 load_image(char const* name
, image_type type
, const char* rpath
,
426 const char* requestingObjectPath
, image_t
** _image
)
428 int32 pheaderSize
, sheaderSize
;
431 char pheaderBuffer
[4096];
440 // Have we already loaded that image? Don't check for add-ons -- we always
442 if (type
!= B_ADD_ON_IMAGE
) {
443 found
= find_loaded_image_by_name(name
, APP_OR_LIBRARY_TYPE
);
445 if (found
== NULL
&& type
!= B_APP_IMAGE
&& gProgramImage
!= NULL
) {
446 // Special case for add-ons that link against the application
447 // executable, with the executable not having a soname set.
448 if (const char* lastSlash
= strrchr(name
, '/')) {
449 if (strcmp(gProgramImage
->name
, lastSlash
+ 1) == 0)
450 found
= gProgramImage
;
455 atomic_add(&found
->ref_count
, 1);
457 KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\") "
458 "already loaded", name
, type
, rpath
);
463 KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\")", name
, type
,
466 strlcpy(path
, name
, sizeof(path
));
468 // find and open the file
469 fd
= open_executable(path
, type
, rpath
, get_program_path(),
470 requestingObjectPath
, sSearchPathSubDir
);
472 FATAL("Cannot open file %s: %s\n", name
, strerror(fd
));
473 KTRACE("rld: load_container(\"%s\"): failed to open file", name
);
477 // normalize the image path
478 status
= _kern_normalize_path(path
, true, path
);
482 // Test again if this image has been registered already - this time,
483 // we can check the full path, not just its name as noted.
484 // You could end up loading an image twice with symbolic links, else.
485 if (type
!= B_ADD_ON_IMAGE
) {
486 found
= find_loaded_image_by_name(path
, APP_OR_LIBRARY_TYPE
);
488 atomic_add(&found
->ref_count
, 1);
491 KTRACE("rld: load_container(\"%s\"): already loaded after all",
497 length
= _kern_read(fd
, 0, &eheader
, sizeof(eheader
));
498 if (length
!= sizeof(eheader
)) {
499 status
= B_NOT_AN_EXECUTABLE
;
500 FATAL("%s: Troubles reading ELF header\n", path
);
504 status
= parse_elf_header(&eheader
, &pheaderSize
, &sheaderSize
);
506 FATAL("%s: Incorrect ELF header\n", path
);
510 // ToDo: what to do about this restriction??
511 if (pheaderSize
> (int)sizeof(pheaderBuffer
)) {
512 FATAL("%s: Cannot handle program headers bigger than %lu\n",
513 path
, sizeof(pheaderBuffer
));
514 status
= B_UNSUPPORTED
;
518 length
= _kern_read(fd
, eheader
.e_phoff
, pheaderBuffer
, pheaderSize
);
519 if (length
!= pheaderSize
) {
520 FATAL("%s: Could not read program headers: %s\n", path
,
526 numRegions
= count_regions(path
, pheaderBuffer
, eheader
.e_phnum
,
527 eheader
.e_phentsize
);
528 if (numRegions
<= 0) {
529 FATAL("%s: Troubles parsing Program headers, numRegions = %" B_PRId32
530 "\n", path
, numRegions
);
535 image
= create_image(name
, path
, numRegions
);
537 FATAL("%s: Failed to allocate image_t object\n", path
);
538 status
= B_NO_MEMORY
;
542 status
= parse_program_headers(image
, pheaderBuffer
, eheader
.e_phnum
,
543 eheader
.e_phentsize
);
547 if (!assert_dynamic_loadable(image
)) {
548 FATAL("%s: Dynamic segment must be loadable (implementation "
549 "restriction)\n", image
->path
);
550 status
= B_UNSUPPORTED
;
554 status
= map_image(fd
, path
, image
, eheader
.e_type
== ET_EXEC
);
556 FATAL("%s: Could not map image: %s\n", image
->path
, strerror(status
));
561 if (!parse_dynamic_segment(image
)) {
562 FATAL("%s: Troubles handling dynamic section\n", image
->path
);
567 if (eheader
.e_entry
!= 0)
568 image
->entry_point
= eheader
.e_entry
+ image
->regions
[0].delta
;
570 analyze_image_haiku_version_and_abi(fd
, image
, eheader
, sheaderSize
,
571 pheaderBuffer
, sizeof(pheaderBuffer
));
573 // If sSearchPathSubDir is unset (meaning, this is the first image we're
574 // loading) we init the search path subdir if the compiler version doesn't
576 if (sSearchPathSubDir
== NULL
) {
578 if ((image
->abi
& B_HAIKU_ABI_MAJOR
) == B_HAIKU_ABI_GCC_4
)
579 sSearchPathSubDir
= "x86";
581 if ((image
->abi
& B_HAIKU_ABI_MAJOR
) == B_HAIKU_ABI_GCC_2
)
582 sSearchPathSubDir
= "x86_gcc2";
586 set_abi_version(image
->abi
);
588 // init gcc version dependent image flags
589 // symbol resolution strategy
590 if (image
->abi
== B_HAIKU_ABI_GCC_2_ANCIENT
)
591 image
->find_undefined_symbol
= find_undefined_symbol_beos
;
593 // init version infos
594 status
= init_image_version_infos(image
);
597 register_image(image
, fd
, path
);
598 image_event(image
, IMAGE_EVENT_LOADED
);
602 enqueue_loaded_image(image
);
606 KTRACE("rld: load_container(\"%s\"): done: id: %" B_PRId32
" (ABI: %#"
607 B_PRIx32
")", name
, image
->id
, image
->abi
);
614 delete_image_struct(image
);
618 KTRACE("rld: load_container(\"%s\"): failed: %s", name
,