xref: /haiku/src/system/runtime_loader/elf_load_image.cpp (revision 3c08adef21129761f27ae654a1c5d1705786691a)
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 			default:
343 				continue;
344 
345 			// TODO: Implement:
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
352 			//		function arrays.
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).
357 		}
358 	}
359 
360 	// lets make sure we found all the required sections
361 	if (!image->symhash || !image->syms || !image->strtab)
362 		return false;
363 
364 	if (sonameOffset >= 0)
365 		strlcpy(image->name, STRING(image, sonameOffset), sizeof(image->name));
366 
367 	return true;
368 }
369 
370 
371 // #pragma mark -
372 
373 
374 status_t
375 parse_elf_header(elf_ehdr* eheader, int32* _pheaderSize,
376 	int32* _sheaderSize)
377 {
378 	if (memcmp(eheader->e_ident, ELFMAG, 4) != 0)
379 		return B_NOT_AN_EXECUTABLE;
380 
381 	if (eheader->e_ident[4] != ELF_CLASS)
382 		return B_NOT_AN_EXECUTABLE;
383 
384 	if (eheader->e_phoff == 0)
385 		return B_NOT_AN_EXECUTABLE;
386 
387 	if (eheader->e_phentsize < sizeof(elf_phdr))
388 		return B_NOT_AN_EXECUTABLE;
389 
390 	*_pheaderSize = eheader->e_phentsize * eheader->e_phnum;
391 	*_sheaderSize = eheader->e_shentsize * eheader->e_shnum;
392 
393 	if (*_pheaderSize <= 0 || *_sheaderSize <= 0)
394 		return B_NOT_AN_EXECUTABLE;
395 
396 	return B_OK;
397 }
398 
399 
400 status_t
401 load_image(char const* name, image_type type, const char* rpath,
402 	const char* requestingObjectPath, image_t** _image)
403 {
404 	int32 pheaderSize, sheaderSize;
405 	char path[PATH_MAX];
406 	ssize_t length;
407 	char pheaderBuffer[4096];
408 	int32 numRegions;
409 	image_t* found;
410 	image_t* image;
411 	status_t status;
412 	int fd;
413 
414 	elf_ehdr eheader;
415 
416 	// Have we already loaded that image? Don't check for add-ons -- we always
417 	// reload them.
418 	if (type != B_ADD_ON_IMAGE) {
419 		found = find_loaded_image_by_name(name, APP_OR_LIBRARY_TYPE);
420 
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;
427 			}
428 		}
429 
430 		if (found) {
431 			atomic_add(&found->ref_count, 1);
432 			*_image = found;
433 			KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\") "
434 				"already loaded", name, type, rpath);
435 			return B_OK;
436 		}
437 	}
438 
439 	KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\")", name, type,
440 		rpath);
441 
442 	strlcpy(path, name, sizeof(path));
443 
444 	// find and open the file
445 	fd = open_executable(path, type, rpath, get_program_path(),
446 		requestingObjectPath, sSearchPathSubDir);
447 	if (fd < 0) {
448 		FATAL("Cannot open file %s: %s\n", name, strerror(fd));
449 		KTRACE("rld: load_container(\"%s\"): failed to open file", name);
450 		return fd;
451 	}
452 
453 	// normalize the image path
454 	status = _kern_normalize_path(path, true, path);
455 	if (status != B_OK)
456 		goto err1;
457 
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);
463 		if (found) {
464 			atomic_add(&found->ref_count, 1);
465 			*_image = found;
466 			_kern_close(fd);
467 			KTRACE("rld: load_container(\"%s\"): already loaded after all",
468 				name);
469 			return B_OK;
470 		}
471 	}
472 
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);
477 		goto err1;
478 	}
479 
480 	status = parse_elf_header(&eheader, &pheaderSize, &sheaderSize);
481 	if (status < B_OK) {
482 		FATAL("%s: Incorrect ELF header\n", path);
483 		goto err1;
484 	}
485 
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;
491 		goto err1;
492 	}
493 
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,
497 			strerror(length));
498 		status = B_BAD_DATA;
499 		goto err1;
500 	}
501 
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);
507 		status = B_BAD_DATA;
508 		goto err1;
509 	}
510 
511 	image = create_image(name, path, numRegions);
512 	if (image == NULL) {
513 		FATAL("%s: Failed to allocate image_t object\n", path);
514 		status = B_NO_MEMORY;
515 		goto err1;
516 	}
517 
518 	status = parse_program_headers(image, pheaderBuffer, eheader.e_phnum,
519 		eheader.e_phentsize);
520 	if (status < B_OK)
521 		goto err2;
522 
523 	if (!assert_dynamic_loadable(image)) {
524 		FATAL("%s: Dynamic segment must be loadable (implementation "
525 			"restriction)\n", image->path);
526 		status = B_UNSUPPORTED;
527 		goto err2;
528 	}
529 
530 	status = map_image(fd, path, image, eheader.e_type == ET_EXEC);
531 	if (status < B_OK) {
532 		FATAL("%s: Could not map image: %s\n", image->path, strerror(status));
533 		status = B_ERROR;
534 		goto err2;
535 	}
536 
537 	if (!parse_dynamic_segment(image)) {
538 		FATAL("%s: Troubles handling dynamic section\n", image->path);
539 		status = B_BAD_DATA;
540 		goto err3;
541 	}
542 
543 	if (eheader.e_entry != 0)
544 		image->entry_point = eheader.e_entry + image->regions[0].delta;
545 
546 	analyze_image_haiku_version_and_abi(fd, image, eheader, sheaderSize,
547 		pheaderBuffer, sizeof(pheaderBuffer));
548 
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) {
552 		#if __GNUC__ == 2
553 			if ((image->abi & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_4)
554 				sSearchPathSubDir = "x86";
555 		#elif __GNUC__ >= 4
556 			if ((image->abi & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_2)
557 				sSearchPathSubDir = "x86_gcc2";
558 		#endif
559 	}
560 
561 	set_abi_version(image->abi);
562 
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;
567 
568 	// init version infos
569 	status = init_image_version_infos(image);
570 
571 	image->type = type;
572 	register_image(image, fd, path);
573 	image_event(image, IMAGE_EVENT_LOADED);
574 
575 	_kern_close(fd);
576 
577 	enqueue_loaded_image(image);
578 
579 	*_image = image;
580 
581 	KTRACE("rld: load_container(\"%s\"): done: id: %" B_PRId32 " (ABI: %#"
582 		B_PRIx32 ")", name, image->id, image->abi);
583 
584 	return B_OK;
585 
586 err3:
587 	unmap_image(image);
588 err2:
589 	delete_image_struct(image);
590 err1:
591 	_kern_close(fd);
592 
593 	KTRACE("rld: load_container(\"%s\"): failed: %s", name,
594 		strerror(status));
595 
596 	return status;
597 }
598