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