xref: /haiku/src/system/runtime_loader/elf_load_image.cpp (revision a07cdb6e9f8e484b6ba9f209fbeb144e906d3405)
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 appropiate 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_STACK:
79 				// we don't use it
80 				break;
81 			case PT_TLS:
82 				// will be handled at some other place
83 				break;
84 			default:
85 				FATAL("%s: Unhandled pheader type in count 0x%" B_PRIx32 "\n",
86 					imagePath, pheaders->p_type);
87 				break;
88 		}
89 	}
90 
91 	return count;
92 }
93 
94 
95 static status_t
96 parse_program_headers(image_t* image, char* buff, int phnum, int phentsize)
97 {
98 	elf_phdr* pheader;
99 	int regcount;
100 	int i;
101 
102 	image->dso_tls_id = unsigned(-1);
103 
104 	regcount = 0;
105 	for (i = 0; i < phnum; i++) {
106 		pheader = (elf_phdr*)(buff + i * phentsize);
107 
108 		switch (pheader->p_type) {
109 			case PT_NULL:
110 				/* NOP header */
111 				break;
112 			case PT_LOAD:
113 				if (pheader->p_memsz == pheader->p_filesz) {
114 					/*
115 					 * everything in one area
116 					 */
117 					image->regions[regcount].start = pheader->p_vaddr;
118 					image->regions[regcount].size = pheader->p_memsz;
119 					image->regions[regcount].vmstart
120 						= PAGE_BASE(pheader->p_vaddr);
121 					image->regions[regcount].vmsize
122 						= TO_PAGE_SIZE(pheader->p_memsz
123 							+ PAGE_OFFSET(pheader->p_vaddr));
124 					image->regions[regcount].fdstart = pheader->p_offset;
125 					image->regions[regcount].fdsize = pheader->p_filesz;
126 					image->regions[regcount].delta = 0;
127 					image->regions[regcount].flags = 0;
128 					if (pheader->p_flags & PF_WRITE) {
129 						// this is a writable segment
130 						image->regions[regcount].flags |= RFLAG_RW;
131 					}
132 				} else {
133 					/*
134 					 * may require splitting
135 					 */
136 					addr_t A = TO_PAGE_SIZE(pheader->p_vaddr
137 						+ pheader->p_memsz);
138 					addr_t B = TO_PAGE_SIZE(pheader->p_vaddr
139 						+ pheader->p_filesz);
140 
141 					image->regions[regcount].start = pheader->p_vaddr;
142 					image->regions[regcount].size = pheader->p_filesz;
143 					image->regions[regcount].vmstart
144 						= PAGE_BASE(pheader->p_vaddr);
145 					image->regions[regcount].vmsize
146 						= TO_PAGE_SIZE(pheader->p_filesz
147 							+ PAGE_OFFSET(pheader->p_vaddr));
148 					image->regions[regcount].fdstart = pheader->p_offset;
149 					image->regions[regcount].fdsize = pheader->p_filesz;
150 					image->regions[regcount].delta = 0;
151 					image->regions[regcount].flags = 0;
152 					if (pheader->p_flags & PF_WRITE) {
153 						// this is a writable segment
154 						image->regions[regcount].flags |= RFLAG_RW;
155 					}
156 
157 					if (A != B) {
158 						/*
159 						 * yeah, it requires splitting
160 						 */
161 						regcount += 1;
162 						image->regions[regcount].start = pheader->p_vaddr;
163 						image->regions[regcount].size
164 							= pheader->p_memsz - pheader->p_filesz;
165 						image->regions[regcount].vmstart
166 							= image->regions[regcount-1].vmstart
167 								+ image->regions[regcount-1].vmsize;
168 						image->regions[regcount].vmsize
169 							= TO_PAGE_SIZE(pheader->p_memsz
170 									+ PAGE_OFFSET(pheader->p_vaddr))
171 								- image->regions[regcount-1].vmsize;
172 						image->regions[regcount].fdstart = 0;
173 						image->regions[regcount].fdsize = 0;
174 						image->regions[regcount].delta = 0;
175 						image->regions[regcount].flags = RFLAG_ANON;
176 						if (pheader->p_flags & PF_WRITE) {
177 							// this is a writable segment
178 							image->regions[regcount].flags |= RFLAG_RW;
179 						}
180 					}
181 				}
182 				regcount += 1;
183 				break;
184 			case PT_DYNAMIC:
185 				image->dynamic_ptr = pheader->p_vaddr;
186 				break;
187 			case PT_INTERP:
188 				// should check here for appropiate interpreter
189 				break;
190 			case PT_NOTE:
191 				// unsupported
192 				break;
193 			case PT_SHLIB:
194 				// undefined semantics
195 				break;
196 			case PT_PHDR:
197 				// we don't use it
198 				break;
199 			case PT_STACK:
200 				// we don't use it
201 				break;
202 			case PT_TLS:
203 				image->dso_tls_id
204 					= TLSBlockTemplates::Get().Register(
205 						TLSBlockTemplate((void*)pheader->p_vaddr,
206 							pheader->p_filesz, pheader->p_memsz));
207 				break;
208 			default:
209 				FATAL("%s: Unhandled pheader type in parse 0x%" B_PRIx32 "\n",
210 					image->path, pheader->p_type);
211 				return B_BAD_DATA;
212 		}
213 	}
214 
215 	return B_OK;
216 }
217 
218 
219 static bool
220 assert_dynamic_loadable(image_t* image)
221 {
222 	uint32 i;
223 
224 	if (!image->dynamic_ptr)
225 		return true;
226 
227 	for (i = 0; i < image->num_regions; i++) {
228 		if (image->dynamic_ptr >= image->regions[i].start
229 			&& image->dynamic_ptr
230 				< image->regions[i].start + image->regions[i].size) {
231 			return true;
232 		}
233 	}
234 
235 	return false;
236 }
237 
238 
239 static bool
240 parse_dynamic_segment(image_t* image)
241 {
242 	elf_dyn* d;
243 	int i;
244 	int sonameOffset = -1;
245 
246 	image->symhash = 0;
247 	image->syms = 0;
248 	image->strtab = 0;
249 
250 	d = (elf_dyn*)image->dynamic_ptr;
251 	if (!d)
252 		return true;
253 
254 	for (i = 0; d[i].d_tag != DT_NULL; i++) {
255 		switch (d[i].d_tag) {
256 			case DT_NEEDED:
257 				image->num_needed += 1;
258 				break;
259 			case DT_HASH:
260 				image->symhash
261 					= (uint32*)(d[i].d_un.d_ptr + image->regions[0].delta);
262 				break;
263 			case DT_STRTAB:
264 				image->strtab
265 					= (char*)(d[i].d_un.d_ptr + image->regions[0].delta);
266 				break;
267 			case DT_SYMTAB:
268 				image->syms = (elf_sym*)
269 					(d[i].d_un.d_ptr + image->regions[0].delta);
270 				break;
271 			case DT_REL:
272 				image->rel = (elf_rel*)
273 					(d[i].d_un.d_ptr + image->regions[0].delta);
274 				break;
275 			case DT_RELSZ:
276 				image->rel_len = d[i].d_un.d_val;
277 				break;
278 			case DT_RELA:
279 				image->rela = (elf_rela*)
280 					(d[i].d_un.d_ptr + image->regions[0].delta);
281 				break;
282 			case DT_RELASZ:
283 				image->rela_len = d[i].d_un.d_val;
284 				break;
285 			case DT_JMPREL:
286 				// procedure linkage table relocations
287 				image->pltrel = (elf_rel*)
288 					(d[i].d_un.d_ptr + image->regions[0].delta);
289 				break;
290 			case DT_PLTRELSZ:
291 				image->pltrel_len = d[i].d_un.d_val;
292 				break;
293 			case DT_INIT:
294 				image->init_routine
295 					= (d[i].d_un.d_ptr + image->regions[0].delta);
296 				break;
297 			case DT_FINI:
298 				image->term_routine
299 					= (d[i].d_un.d_ptr + image->regions[0].delta);
300 				break;
301 			case DT_SONAME:
302 				sonameOffset = d[i].d_un.d_val;
303 				break;
304 			case DT_VERSYM:
305 				image->symbol_versions = (elf_versym*)
306 					(d[i].d_un.d_ptr + image->regions[0].delta);
307 				break;
308 			case DT_VERDEF:
309 				image->version_definitions = (elf_verdef*)
310 					(d[i].d_un.d_ptr + image->regions[0].delta);
311 				break;
312 			case DT_VERDEFNUM:
313 				image->num_version_definitions = d[i].d_un.d_val;
314 				break;
315 			case DT_VERNEED:
316 				image->needed_versions = (elf_verneed*)
317 					(d[i].d_un.d_ptr + image->regions[0].delta);
318 				break;
319 			case DT_VERNEEDNUM:
320 				image->num_needed_versions = d[i].d_un.d_val;
321 				break;
322 			case DT_SYMBOLIC:
323 				image->flags |= RFLAG_SYMBOLIC;
324 				break;
325 			case DT_FLAGS:
326 			{
327 				uint32 flags = d[i].d_un.d_val;
328 				if ((flags & DF_SYMBOLIC) != 0)
329 					image->flags |= RFLAG_SYMBOLIC;
330 				if ((flags & DF_STATIC_TLS) != 0) {
331 					FATAL("Static TLS model is not supported.\n");
332 					return false;
333 				}
334 				break;
335 			}
336 			default:
337 				continue;
338 
339 			// TODO: Implement:
340 			// DT_RELENT: The size of a DT_REL entry.
341 			// DT_RELAENT: The size of a DT_RELA entry.
342 			// DT_SYMENT: The size of a symbol table entry.
343 			// DT_PLTREL: The type of the PLT relocation entries (DT_JMPREL).
344 			// DT_BIND_NOW/DF_BIND_NOW: No lazy binding allowed.
345 			// DT_INIT_ARRAY[SZ], DT_FINI_ARRAY[SZ]: Initialization/termination
346 			//		function arrays.
347 			// DT_PREINIT_ARRAY[SZ]: Preinitialization function array.
348 			// DT_RUNPATH: Library search path (supersedes DT_RPATH).
349 			// DT_TEXTREL/DF_TEXTREL: Indicates whether text relocations are
350 			//		required (for optimization purposes only).
351 		}
352 	}
353 
354 	// lets make sure we found all the required sections
355 	if (!image->symhash || !image->syms || !image->strtab)
356 		return false;
357 
358 	if (sonameOffset >= 0)
359 		strlcpy(image->name, STRING(image, sonameOffset), sizeof(image->name));
360 
361 	return true;
362 }
363 
364 
365 // #pragma mark -
366 
367 
368 status_t
369 parse_elf_header(elf_ehdr* eheader, int32* _pheaderSize,
370 	int32* _sheaderSize)
371 {
372 	if (memcmp(eheader->e_ident, ELF_MAGIC, 4) != 0)
373 		return B_NOT_AN_EXECUTABLE;
374 
375 	if (eheader->e_ident[4] != ELF_CLASS)
376 		return B_NOT_AN_EXECUTABLE;
377 
378 	if (eheader->e_phoff == 0)
379 		return B_NOT_AN_EXECUTABLE;
380 
381 	if (eheader->e_phentsize < sizeof(elf_phdr))
382 		return B_NOT_AN_EXECUTABLE;
383 
384 	*_pheaderSize = eheader->e_phentsize * eheader->e_phnum;
385 	*_sheaderSize = eheader->e_shentsize * eheader->e_shnum;
386 
387 	if (*_pheaderSize <= 0 || *_sheaderSize <= 0)
388 		return B_NOT_AN_EXECUTABLE;
389 
390 	return B_OK;
391 }
392 
393 
394 status_t
395 load_image(char const* name, image_type type, const char* rpath,
396 	const char* requestingObjectPath, image_t** _image)
397 {
398 	int32 pheaderSize, sheaderSize;
399 	char path[PATH_MAX];
400 	ssize_t length;
401 	char pheaderBuffer[4096];
402 	int32 numRegions;
403 	image_t* found;
404 	image_t* image;
405 	status_t status;
406 	int fd;
407 
408 	elf_ehdr eheader;
409 
410 	// Have we already loaded that image? Don't check for add-ons -- we always
411 	// reload them.
412 	if (type != B_ADD_ON_IMAGE) {
413 		found = find_loaded_image_by_name(name, APP_OR_LIBRARY_TYPE);
414 
415 		if (found == NULL && type != B_APP_IMAGE && gProgramImage != NULL) {
416 			// Special case for add-ons that link against the application
417 			// executable, with the executable not having a soname set.
418 			if (const char* lastSlash = strrchr(name, '/')) {
419 				if (strcmp(gProgramImage->name, lastSlash + 1) == 0)
420 					found = gProgramImage;
421 			}
422 		}
423 
424 		if (found) {
425 			atomic_add(&found->ref_count, 1);
426 			*_image = found;
427 			KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\") "
428 				"already loaded", name, type, rpath);
429 			return B_OK;
430 		}
431 	}
432 
433 	KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\")", name, type,
434 		rpath);
435 
436 	strlcpy(path, name, sizeof(path));
437 
438 	// find and open the file
439 	fd = open_executable(path, type, rpath, get_program_path(),
440 		requestingObjectPath, sSearchPathSubDir);
441 	if (fd < 0) {
442 		FATAL("Cannot open file %s: %s\n", name, strerror(fd));
443 		KTRACE("rld: load_container(\"%s\"): failed to open file", name);
444 		return fd;
445 	}
446 
447 	// normalize the image path
448 	status = _kern_normalize_path(path, true, path);
449 	if (status != B_OK)
450 		goto err1;
451 
452 	// Test again if this image has been registered already - this time,
453 	// we can check the full path, not just its name as noted.
454 	// You could end up loading an image twice with symbolic links, else.
455 	if (type != B_ADD_ON_IMAGE) {
456 		found = find_loaded_image_by_name(path, APP_OR_LIBRARY_TYPE);
457 		if (found) {
458 			atomic_add(&found->ref_count, 1);
459 			*_image = found;
460 			_kern_close(fd);
461 			KTRACE("rld: load_container(\"%s\"): already loaded after all",
462 				name);
463 			return B_OK;
464 		}
465 	}
466 
467 	length = _kern_read(fd, 0, &eheader, sizeof(eheader));
468 	if (length != sizeof(eheader)) {
469 		status = B_NOT_AN_EXECUTABLE;
470 		FATAL("%s: Troubles reading ELF header\n", path);
471 		goto err1;
472 	}
473 
474 	status = parse_elf_header(&eheader, &pheaderSize, &sheaderSize);
475 	if (status < B_OK) {
476 		FATAL("%s: Incorrect ELF header\n", path);
477 		goto err1;
478 	}
479 
480 	// ToDo: what to do about this restriction??
481 	if (pheaderSize > (int)sizeof(pheaderBuffer)) {
482 		FATAL("%s: Cannot handle program headers bigger than %lu\n",
483 			path, sizeof(pheaderBuffer));
484 		status = B_UNSUPPORTED;
485 		goto err1;
486 	}
487 
488 	length = _kern_read(fd, eheader.e_phoff, pheaderBuffer, pheaderSize);
489 	if (length != pheaderSize) {
490 		FATAL("%s: Could not read program headers: %s\n", path,
491 			strerror(length));
492 		status = B_BAD_DATA;
493 		goto err1;
494 	}
495 
496 	numRegions = count_regions(path, pheaderBuffer, eheader.e_phnum,
497 		eheader.e_phentsize);
498 	if (numRegions <= 0) {
499 		FATAL("%s: Troubles parsing Program headers, numRegions = %" B_PRId32
500 			"\n", path, numRegions);
501 		status = B_BAD_DATA;
502 		goto err1;
503 	}
504 
505 	image = create_image(name, path, numRegions);
506 	if (image == NULL) {
507 		FATAL("%s: Failed to allocate image_t object\n", path);
508 		status = B_NO_MEMORY;
509 		goto err1;
510 	}
511 
512 	status = parse_program_headers(image, pheaderBuffer, eheader.e_phnum,
513 		eheader.e_phentsize);
514 	if (status < B_OK)
515 		goto err2;
516 
517 	if (!assert_dynamic_loadable(image)) {
518 		FATAL("%s: Dynamic segment must be loadable (implementation "
519 			"restriction)\n", image->path);
520 		status = B_UNSUPPORTED;
521 		goto err2;
522 	}
523 
524 	status = map_image(fd, path, image);
525 	if (status < B_OK) {
526 		FATAL("%s: Could not map image: %s\n", image->path, strerror(status));
527 		status = B_ERROR;
528 		goto err2;
529 	}
530 
531 	if (!parse_dynamic_segment(image)) {
532 		FATAL("%s: Troubles handling dynamic section\n", image->path);
533 		status = B_BAD_DATA;
534 		goto err3;
535 	}
536 
537 	if (eheader.e_entry != 0)
538 		image->entry_point = eheader.e_entry + image->regions[0].delta;
539 
540 	analyze_image_haiku_version_and_abi(fd, image, eheader, sheaderSize,
541 		pheaderBuffer, sizeof(pheaderBuffer));
542 
543 	// If this is the executable image, we init the search path
544 	// subdir, if the compiler version doesn't match ours.
545 	if (type == B_APP_IMAGE) {
546 		#if __GNUC__ == 2
547 			if ((image->abi & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_4)
548 				sSearchPathSubDir = "x86";
549 		#elif __GNUC__ == 4
550 			if ((image->abi & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_2)
551 				sSearchPathSubDir = "x86_gcc2";
552 		#endif
553 	}
554 
555 	set_abi_version(image->abi);
556 
557 	// init gcc version dependent image flags
558 	// symbol resolution strategy
559 	if (image->abi == B_HAIKU_ABI_GCC_2_ANCIENT)
560 		image->find_undefined_symbol = find_undefined_symbol_beos;
561 
562 	// init version infos
563 	status = init_image_version_infos(image);
564 
565 	image->type = type;
566 	register_image(image, fd, path);
567 	image_event(image, IMAGE_EVENT_LOADED);
568 
569 	_kern_close(fd);
570 
571 	enqueue_loaded_image(image);
572 
573 	*_image = image;
574 
575 	KTRACE("rld: load_container(\"%s\"): done: id: %" B_PRId32 " (ABI: %#"
576 		B_PRIx32 ")", name, image->id, image->abi);
577 
578 	return B_OK;
579 
580 err3:
581 	unmap_image(image);
582 err2:
583 	delete_image_struct(image);
584 err1:
585 	_kern_close(fd);
586 
587 	KTRACE("rld: load_container(\"%s\"): failed: %s", name,
588 		strerror(status));
589 
590 	return status;
591 }
592