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