xref: /haiku/src/system/runtime_loader/elf_load_image.cpp (revision c42868a015daa160e093679b2637b1cf9f0b26ba)
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_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;
91 		}
92 	}
93 
94 	return count;
95 }
96 
97 
98 static status_t
99 parse_program_headers(image_t* image, char* buff, int phnum, int phentsize)
100 {
101 	elf_phdr* pheader;
102 	int regcount;
103 	int i;
104 
105 	image->dso_tls_id = unsigned(-1);
106 
107 	regcount = 0;
108 	for (i = 0; i < phnum; i++) {
109 		pheader = (elf_phdr*)(buff + i * phentsize);
110 
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) {
117 					/*
118 					 * everything in one area
119 					 */
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;
134 					}
135 				} else {
136 					/*
137 					 * may require splitting
138 					 */
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);
143 
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;
158 					}
159 
160 					if (A != B) {
161 						/*
162 						 * yeah, it requires splitting
163 						 */
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;
182 						}
183 					}
184 				}
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;
218 		}
219 	}
220 
221 	return B_OK;
222 }
223 
224 
225 static bool
226 assert_dynamic_loadable(image_t* image)
227 {
228 	uint32 i;
229 
230 	if (!image->dynamic_ptr)
231 		return true;
232 
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;
238 		}
239 	}
240 
241 	return false;
242 }
243 
244 
245 static bool
246 parse_dynamic_segment(image_t* image)
247 {
248 	elf_dyn* d;
249 	int i;
250 	int sonameOffset = -1;
251 
252 	image->symhash = 0;
253 	image->syms = 0;
254 	image->strtab = 0;
255 
256 	d = (elf_dyn*)image->dynamic_ptr;
257 	if (!d)
258 		return true;
259 
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:
332 			{
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;
339 				}
340 				break;
341 			}
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;
371 
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).
381 		}
382 	}
383 
384 	// lets make sure we found all the required sections
385 	if (!image->symhash || !image->syms || !image->strtab)
386 		return false;
387 
388 	if (sonameOffset >= 0)
389 		strlcpy(image->name, STRING(image, sonameOffset), sizeof(image->name));
390 
391 	return true;
392 }
393 
394 
395 // #pragma mark -
396 
397 
398 status_t
399 parse_elf_header(elf_ehdr* eheader, int32* _pheaderSize,
400 	int32* _sheaderSize)
401 {
402 	if (memcmp(eheader->e_ident, ELFMAG, 4) != 0)
403 		return B_NOT_AN_EXECUTABLE;
404 
405 	if (eheader->e_ident[4] != ELF_CLASS)
406 		return B_NOT_AN_EXECUTABLE;
407 
408 	if (eheader->e_phoff == 0)
409 		return B_NOT_AN_EXECUTABLE;
410 
411 	if (eheader->e_phentsize < sizeof(elf_phdr))
412 		return B_NOT_AN_EXECUTABLE;
413 
414 	*_pheaderSize = eheader->e_phentsize * eheader->e_phnum;
415 	*_sheaderSize = eheader->e_shentsize * eheader->e_shnum;
416 
417 	if (*_pheaderSize <= 0 || *_sheaderSize <= 0)
418 		return B_NOT_AN_EXECUTABLE;
419 
420 	return B_OK;
421 }
422 
423 
424 status_t
425 load_image(char const* name, image_type type, const char* rpath,
426 	const char* requestingObjectPath, image_t** _image)
427 {
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;
437 
438 	elf_ehdr eheader;
439 
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);
444 
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;
451 			}
452 		}
453 
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;
460 		}
461 	}
462 
463 	KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\")", name, type,
464 		rpath);
465 
466 	strlcpy(path, name, sizeof(path));
467 
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;
475 	}
476 
477 	// normalize the image path
478 	status = _kern_normalize_path(path, true, path);
479 	if (status != B_OK)
480 		goto err1;
481 
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;
494 		}
495 	}
496 
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;
502 	}
503 
504 	status = parse_elf_header(&eheader, &pheaderSize, &sheaderSize);
505 	if (status < B_OK) {
506 		FATAL("%s: Incorrect ELF header\n", path);
507 		goto err1;
508 	}
509 
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;
516 	}
517 
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;
524 	}
525 
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;
533 	}
534 
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;
540 	}
541 
542 	status = parse_program_headers(image, pheaderBuffer, eheader.e_phnum,
543 		eheader.e_phentsize);
544 	if (status < B_OK)
545 		goto err2;
546 
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;
552 	}
553 
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;
559 	}
560 
561 	if (!parse_dynamic_segment(image)) {
562 		FATAL("%s: Troubles handling dynamic section\n", image->path);
563 		status = B_BAD_DATA;
564 		goto err3;
565 	}
566 
567 	if (eheader.e_entry != 0)
568 		image->entry_point = eheader.e_entry + image->regions[0].delta;
569 
570 	analyze_image_haiku_version_and_abi(fd, image, eheader, sheaderSize,
571 		pheaderBuffer, sizeof(pheaderBuffer));
572 
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
584 	}
585 
586 	set_abi_version(image->abi);
587 
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;
592 
593 	// init version infos
594 	status = init_image_version_infos(image);
595 
596 	image->type = type;
597 	register_image(image, fd, path);
598 	image_event(image, IMAGE_EVENT_LOADED);
599 
600 	_kern_close(fd);
601 
602 	enqueue_loaded_image(image);
603 
604 	*_image = image;
605 
606 	KTRACE("rld: load_container(\"%s\"): done: id: %" B_PRId32 " (ABI: %#"
607 		B_PRIx32 ")", name, image->id, image->abi);
608 
609 	return B_OK;
610 
611 err3:
612 	unmap_image(image);
613 err2:
614 	delete_image_struct(image);
615 err1:
616 	_kern_close(fd);
617 
618 	KTRACE("rld: load_container(\"%s\"): failed: %s", name,
619 		strerror(status));
620 
621 	return status;
622 }
623