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 appropiate 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");
346 // DT_RELENT: The size of a DT_REL entry.
347 // DT_RELAENT: The size of a DT_RELA entry.
348 // DT_SYMENT: The size of a symbol table entry.
349 // DT_PLTREL: The type of the PLT relocation entries (DT_JMPREL).
350 // DT_BIND_NOW/DF_BIND_NOW: No lazy binding allowed.
351 // DT_INIT_ARRAY[SZ], DT_FINI_ARRAY[SZ]: Initialization/termination
353 // DT_PREINIT_ARRAY[SZ]: Preinitialization function array.
354 // DT_RUNPATH: Library search path (supersedes DT_RPATH).
355 // DT_TEXTREL/DF_TEXTREL: Indicates whether text relocations are
356 // required (for optimization purposes only).
360 // lets make sure we found all the required sections
361 if (!image
->symhash
|| !image
->syms
|| !image
->strtab
)
364 if (sonameOffset
>= 0)
365 strlcpy(image
->name
, STRING(image
, sonameOffset
), sizeof(image
->name
));
375 parse_elf_header(elf_ehdr
* eheader
, int32
* _pheaderSize
,
378 if (memcmp(eheader
->e_ident
, ELF_MAGIC
, 4) != 0)
379 return B_NOT_AN_EXECUTABLE
;
381 if (eheader
->e_ident
[4] != ELF_CLASS
)
382 return B_NOT_AN_EXECUTABLE
;
384 if (eheader
->e_phoff
== 0)
385 return B_NOT_AN_EXECUTABLE
;
387 if (eheader
->e_phentsize
< sizeof(elf_phdr
))
388 return B_NOT_AN_EXECUTABLE
;
390 *_pheaderSize
= eheader
->e_phentsize
* eheader
->e_phnum
;
391 *_sheaderSize
= eheader
->e_shentsize
* eheader
->e_shnum
;
393 if (*_pheaderSize
<= 0 || *_sheaderSize
<= 0)
394 return B_NOT_AN_EXECUTABLE
;
401 load_image(char const* name
, image_type type
, const char* rpath
,
402 const char* requestingObjectPath
, image_t
** _image
)
404 int32 pheaderSize
, sheaderSize
;
407 char pheaderBuffer
[4096];
416 // Have we already loaded that image? Don't check for add-ons -- we always
418 if (type
!= B_ADD_ON_IMAGE
) {
419 found
= find_loaded_image_by_name(name
, APP_OR_LIBRARY_TYPE
);
421 if (found
== NULL
&& type
!= B_APP_IMAGE
&& gProgramImage
!= NULL
) {
422 // Special case for add-ons that link against the application
423 // executable, with the executable not having a soname set.
424 if (const char* lastSlash
= strrchr(name
, '/')) {
425 if (strcmp(gProgramImage
->name
, lastSlash
+ 1) == 0)
426 found
= gProgramImage
;
431 atomic_add(&found
->ref_count
, 1);
433 KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\") "
434 "already loaded", name
, type
, rpath
);
439 KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\")", name
, type
,
442 strlcpy(path
, name
, sizeof(path
));
444 // find and open the file
445 fd
= open_executable(path
, type
, rpath
, get_program_path(),
446 requestingObjectPath
, sSearchPathSubDir
);
448 FATAL("Cannot open file %s: %s\n", name
, strerror(fd
));
449 KTRACE("rld: load_container(\"%s\"): failed to open file", name
);
453 // normalize the image path
454 status
= _kern_normalize_path(path
, true, path
);
458 // Test again if this image has been registered already - this time,
459 // we can check the full path, not just its name as noted.
460 // You could end up loading an image twice with symbolic links, else.
461 if (type
!= B_ADD_ON_IMAGE
) {
462 found
= find_loaded_image_by_name(path
, APP_OR_LIBRARY_TYPE
);
464 atomic_add(&found
->ref_count
, 1);
467 KTRACE("rld: load_container(\"%s\"): already loaded after all",
473 length
= _kern_read(fd
, 0, &eheader
, sizeof(eheader
));
474 if (length
!= sizeof(eheader
)) {
475 status
= B_NOT_AN_EXECUTABLE
;
476 FATAL("%s: Troubles reading ELF header\n", path
);
480 status
= parse_elf_header(&eheader
, &pheaderSize
, &sheaderSize
);
482 FATAL("%s: Incorrect ELF header\n", path
);
486 // ToDo: what to do about this restriction??
487 if (pheaderSize
> (int)sizeof(pheaderBuffer
)) {
488 FATAL("%s: Cannot handle program headers bigger than %lu\n",
489 path
, sizeof(pheaderBuffer
));
490 status
= B_UNSUPPORTED
;
494 length
= _kern_read(fd
, eheader
.e_phoff
, pheaderBuffer
, pheaderSize
);
495 if (length
!= pheaderSize
) {
496 FATAL("%s: Could not read program headers: %s\n", path
,
502 numRegions
= count_regions(path
, pheaderBuffer
, eheader
.e_phnum
,
503 eheader
.e_phentsize
);
504 if (numRegions
<= 0) {
505 FATAL("%s: Troubles parsing Program headers, numRegions = %" B_PRId32
506 "\n", path
, numRegions
);
511 image
= create_image(name
, path
, numRegions
);
513 FATAL("%s: Failed to allocate image_t object\n", path
);
514 status
= B_NO_MEMORY
;
518 status
= parse_program_headers(image
, pheaderBuffer
, eheader
.e_phnum
,
519 eheader
.e_phentsize
);
523 if (!assert_dynamic_loadable(image
)) {
524 FATAL("%s: Dynamic segment must be loadable (implementation "
525 "restriction)\n", image
->path
);
526 status
= B_UNSUPPORTED
;
530 status
= map_image(fd
, path
, image
);
532 FATAL("%s: Could not map image: %s\n", image
->path
, strerror(status
));
537 if (!parse_dynamic_segment(image
)) {
538 FATAL("%s: Troubles handling dynamic section\n", image
->path
);
543 if (eheader
.e_entry
!= 0)
544 image
->entry_point
= eheader
.e_entry
+ image
->regions
[0].delta
;
546 analyze_image_haiku_version_and_abi(fd
, image
, eheader
, sheaderSize
,
547 pheaderBuffer
, sizeof(pheaderBuffer
));
549 // If this is the executable image, we init the search path
550 // subdir, if the compiler version doesn't match ours.
551 if (type
== B_APP_IMAGE
) {
553 if ((image
->abi
& B_HAIKU_ABI_MAJOR
) == B_HAIKU_ABI_GCC_4
)
554 sSearchPathSubDir
= "x86";
556 if ((image
->abi
& B_HAIKU_ABI_MAJOR
) == B_HAIKU_ABI_GCC_2
)
557 sSearchPathSubDir
= "x86_gcc2";
561 set_abi_version(image
->abi
);
563 // init gcc version dependent image flags
564 // symbol resolution strategy
565 if (image
->abi
== B_HAIKU_ABI_GCC_2_ANCIENT
)
566 image
->find_undefined_symbol
= find_undefined_symbol_beos
;
568 // init version infos
569 status
= init_image_version_infos(image
);
572 register_image(image
, fd
, path
);
573 image_event(image
, IMAGE_EVENT_LOADED
);
577 enqueue_loaded_image(image
);
581 KTRACE("rld: load_container(\"%s\"): done: id: %" B_PRId32
" (ABI: %#"
582 B_PRIx32
")", name
, image
->id
, image
->abi
);
589 delete_image_struct(image
);
593 KTRACE("rld: load_container(\"%s\"): failed: %s", name
,