headers/bsd: Add sys/queue.h.
[haiku.git] / src / system / runtime_loader / elf_load_image.cpp
blob3822f36266e794cab4c26fe3e72ea7e2ad2f8051
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.
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 */
11 #include "elf_load_image.h"
13 #include <stdio.h>
14 #include <string.h>
16 #include <syscalls.h>
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"
27 static const char* sSearchPathSubDir = NULL;
30 static const char*
31 get_program_path()
33 return gProgramImage != NULL ? gProgramImage->path : NULL;
37 static int32
38 count_regions(const char* imagePath, char const* buff, int phnum, int phentsize)
40 elf_phdr* pheaders;
41 int32 count = 0;
42 int i;
44 for (i = 0; i < phnum; i++) {
45 pheaders = (elf_phdr*)(buff + i * phentsize);
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);
59 if (A != B)
60 count += 1;
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_RELRO:
79 // not implemented yet, but can be ignored
80 break;
81 case PT_STACK:
82 // we don't use it
83 break;
84 case PT_TLS:
85 // will be handled at some other place
86 break;
87 default:
88 FATAL("%s: Unhandled pheader type in count 0x%" B_PRIx32 "\n",
89 imagePath, pheaders->p_type);
90 break;
94 return count;
98 static status_t
99 parse_program_headers(image_t* image, char* buff, int phnum, int phentsize)
101 elf_phdr* pheader;
102 int regcount;
103 int i;
105 image->dso_tls_id = unsigned(-1);
107 regcount = 0;
108 for (i = 0; i < phnum; i++) {
109 pheader = (elf_phdr*)(buff + i * phentsize);
111 switch (pheader->p_type) {
112 case PT_NULL:
113 /* NOP header */
114 break;
115 case PT_LOAD:
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;
135 } else {
137 * may require splitting
139 addr_t A = TO_PAGE_SIZE(pheader->p_vaddr
140 + pheader->p_memsz);
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;
160 if (A != B) {
162 * yeah, it requires splitting
164 regcount += 1;
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;
185 regcount += 1;
186 break;
187 case PT_DYNAMIC:
188 image->dynamic_ptr = pheader->p_vaddr;
189 break;
190 case PT_INTERP:
191 // should check here for appropiate interpreter
192 break;
193 case PT_NOTE:
194 // unsupported
195 break;
196 case PT_SHLIB:
197 // undefined semantics
198 break;
199 case PT_PHDR:
200 // we don't use it
201 break;
202 case PT_RELRO:
203 // not implemented yet, but can be ignored
204 break;
205 case PT_STACK:
206 // we don't use it
207 break;
208 case PT_TLS:
209 image->dso_tls_id
210 = TLSBlockTemplates::Get().Register(
211 TLSBlockTemplate((void*)pheader->p_vaddr,
212 pheader->p_filesz, pheader->p_memsz));
213 break;
214 default:
215 FATAL("%s: Unhandled pheader type in parse 0x%" B_PRIx32 "\n",
216 image->path, pheader->p_type);
217 return B_BAD_DATA;
221 return B_OK;
225 static bool
226 assert_dynamic_loadable(image_t* image)
228 uint32 i;
230 if (!image->dynamic_ptr)
231 return true;
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) {
237 return true;
241 return false;
245 static bool
246 parse_dynamic_segment(image_t* image)
248 elf_dyn* d;
249 int i;
250 int sonameOffset = -1;
252 image->symhash = 0;
253 image->syms = 0;
254 image->strtab = 0;
256 d = (elf_dyn*)image->dynamic_ptr;
257 if (!d)
258 return true;
260 for (i = 0; d[i].d_tag != DT_NULL; i++) {
261 switch (d[i].d_tag) {
262 case DT_NEEDED:
263 image->num_needed += 1;
264 break;
265 case DT_HASH:
266 image->symhash
267 = (uint32*)(d[i].d_un.d_ptr + image->regions[0].delta);
268 break;
269 case DT_STRTAB:
270 image->strtab
271 = (char*)(d[i].d_un.d_ptr + image->regions[0].delta);
272 break;
273 case DT_SYMTAB:
274 image->syms = (elf_sym*)
275 (d[i].d_un.d_ptr + image->regions[0].delta);
276 break;
277 case DT_REL:
278 image->rel = (elf_rel*)
279 (d[i].d_un.d_ptr + image->regions[0].delta);
280 break;
281 case DT_RELSZ:
282 image->rel_len = d[i].d_un.d_val;
283 break;
284 case DT_RELA:
285 image->rela = (elf_rela*)
286 (d[i].d_un.d_ptr + image->regions[0].delta);
287 break;
288 case DT_RELASZ:
289 image->rela_len = d[i].d_un.d_val;
290 break;
291 case DT_JMPREL:
292 // procedure linkage table relocations
293 image->pltrel = (elf_rel*)
294 (d[i].d_un.d_ptr + image->regions[0].delta);
295 break;
296 case DT_PLTRELSZ:
297 image->pltrel_len = d[i].d_un.d_val;
298 break;
299 case DT_INIT:
300 image->init_routine
301 = (d[i].d_un.d_ptr + image->regions[0].delta);
302 break;
303 case DT_FINI:
304 image->term_routine
305 = (d[i].d_un.d_ptr + image->regions[0].delta);
306 break;
307 case DT_SONAME:
308 sonameOffset = d[i].d_un.d_val;
309 break;
310 case DT_VERSYM:
311 image->symbol_versions = (elf_versym*)
312 (d[i].d_un.d_ptr + image->regions[0].delta);
313 break;
314 case DT_VERDEF:
315 image->version_definitions = (elf_verdef*)
316 (d[i].d_un.d_ptr + image->regions[0].delta);
317 break;
318 case DT_VERDEFNUM:
319 image->num_version_definitions = d[i].d_un.d_val;
320 break;
321 case DT_VERNEED:
322 image->needed_versions = (elf_verneed*)
323 (d[i].d_un.d_ptr + image->regions[0].delta);
324 break;
325 case DT_VERNEEDNUM:
326 image->num_needed_versions = d[i].d_un.d_val;
327 break;
328 case DT_SYMBOLIC:
329 image->flags |= RFLAG_SYMBOLIC;
330 break;
331 case DT_FLAGS:
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");
338 return false;
340 break;
342 case DT_INIT_ARRAY:
343 // array of pointers to initialization functions
344 image->init_array = (addr_t*)
345 (d[i].d_un.d_ptr + image->regions[0].delta);
346 break;
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;
350 break;
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);
355 break;
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;
359 break;
360 case DT_FINI_ARRAY:
361 // array of pointers to termination functions
362 image->term_array = (addr_t*)
363 (d[i].d_un.d_ptr + image->regions[0].delta);
364 break;
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;
368 break;
369 default:
370 continue;
372 // TODO: Implement:
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)
386 return false;
388 if (sonameOffset >= 0)
389 strlcpy(image->name, STRING(image, sonameOffset), sizeof(image->name));
391 return true;
395 // #pragma mark -
398 status_t
399 parse_elf_header(elf_ehdr* eheader, int32* _pheaderSize,
400 int32* _sheaderSize)
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;
420 return B_OK;
424 status_t
425 load_image(char const* name, image_type type, const char* rpath,
426 const char* requestingObjectPath, image_t** _image)
428 int32 pheaderSize, sheaderSize;
429 char path[PATH_MAX];
430 ssize_t length;
431 char pheaderBuffer[4096];
432 int32 numRegions;
433 image_t* found;
434 image_t* image;
435 status_t status;
436 int fd;
438 elf_ehdr eheader;
440 // Have we already loaded that image? Don't check for add-ons -- we always
441 // reload them.
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;
454 if (found) {
455 atomic_add(&found->ref_count, 1);
456 *_image = found;
457 KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\") "
458 "already loaded", name, type, rpath);
459 return B_OK;
463 KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\")", name, type,
464 rpath);
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);
471 if (fd < 0) {
472 FATAL("Cannot open file %s: %s\n", name, strerror(fd));
473 KTRACE("rld: load_container(\"%s\"): failed to open file", name);
474 return fd;
477 // normalize the image path
478 status = _kern_normalize_path(path, true, path);
479 if (status != B_OK)
480 goto err1;
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);
487 if (found) {
488 atomic_add(&found->ref_count, 1);
489 *_image = found;
490 _kern_close(fd);
491 KTRACE("rld: load_container(\"%s\"): already loaded after all",
492 name);
493 return B_OK;
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);
501 goto err1;
504 status = parse_elf_header(&eheader, &pheaderSize, &sheaderSize);
505 if (status < B_OK) {
506 FATAL("%s: Incorrect ELF header\n", path);
507 goto err1;
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;
515 goto err1;
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,
521 strerror(length));
522 status = B_BAD_DATA;
523 goto err1;
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);
531 status = B_BAD_DATA;
532 goto err1;
535 image = create_image(name, path, numRegions);
536 if (image == NULL) {
537 FATAL("%s: Failed to allocate image_t object\n", path);
538 status = B_NO_MEMORY;
539 goto err1;
542 status = parse_program_headers(image, pheaderBuffer, eheader.e_phnum,
543 eheader.e_phentsize);
544 if (status < B_OK)
545 goto err2;
547 if (!assert_dynamic_loadable(image)) {
548 FATAL("%s: Dynamic segment must be loadable (implementation "
549 "restriction)\n", image->path);
550 status = B_UNSUPPORTED;
551 goto err2;
554 status = map_image(fd, path, image, eheader.e_type == ET_EXEC);
555 if (status < B_OK) {
556 FATAL("%s: Could not map image: %s\n", image->path, strerror(status));
557 status = B_ERROR;
558 goto err2;
561 if (!parse_dynamic_segment(image)) {
562 FATAL("%s: Troubles handling dynamic section\n", image->path);
563 status = B_BAD_DATA;
564 goto err3;
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
575 // match ours.
576 if (sSearchPathSubDir == NULL) {
577 #if __GNUC__ == 2
578 if ((image->abi & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_4)
579 sSearchPathSubDir = "x86";
580 #elif __GNUC__ >= 4
581 if ((image->abi & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_2)
582 sSearchPathSubDir = "x86_gcc2";
583 #endif
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);
596 image->type = type;
597 register_image(image, fd, path);
598 image_event(image, IMAGE_EVENT_LOADED);
600 _kern_close(fd);
602 enqueue_loaded_image(image);
604 *_image = image;
606 KTRACE("rld: load_container(\"%s\"): done: id: %" B_PRId32 " (ABI: %#"
607 B_PRIx32 ")", name, image->id, image->abi);
609 return B_OK;
611 err3:
612 unmap_image(image);
613 err2:
614 delete_image_struct(image);
615 err1:
616 _kern_close(fd);
618 KTRACE("rld: load_container(\"%s\"): failed: %s", name,
619 strerror(status));
621 return status;