summaryrefslogtreecommitdiff
path: root/emulators/virtualbox-ose-additions/files/patch-src-VBox-Additions-common-crOpenGL-fakedri_drv.c
blob: 623cebfbdfac8c0ea09d6a6d72e5a9d8577bf1d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
--- src/VBox/Additions/common/crOpenGL/fakedri_drv.c.orig	2013-11-28 19:30:42.000000000 +0100
+++ src/VBox/Additions/common/crOpenGL/fakedri_drv.c	2013-12-06 16:03:16.000000000 +0100
@@ -29,6 +29,15 @@
 #include <dlfcn.h>
 #include <elf.h>
 #include <unistd.h>
+
+#include <sys/param.h>
+#if defined(BSD)
+#include <fcntl.h>
+#include <gelf.h>
+#include <libelf.h>
+#include <string.h>
+#endif
+
 /** X server message type definitions. */
 typedef enum {
     X_PROBED,			/* Value was probed */
@@ -50,11 +59,11 @@
 
 //@todo this could be different...
 #ifdef RT_ARCH_AMD64
-# define DRI_DEFAULT_DRIVER_DIR "/usr/lib64/dri:/usr/lib/dri:/usr/lib/x86_64-linux-gnu/dri:/usr/lib/xorg/modules/dri"
-# define DRI_XORG_DRV_DIR "/usr/lib/xorg/modules/drivers/"
+# define DRI_DEFAULT_DRIVER_DIR "/usr/local/lib/dri"
+# define DRI_XORG_DRV_DIR "/usr/local/lib/xorg/modules/drivers/"
 #else
-# define DRI_DEFAULT_DRIVER_DIR "/usr/lib/dri:/usr/lib/i386-linux-gnu/dri:/usr/lib/xorg/modules/dri"
-# define DRI_XORG_DRV_DIR "/usr/lib/xorg/modules/drivers/"
+# define DRI_DEFAULT_DRIVER_DIR "/usr/local/lib/dri"
+# define DRI_XORG_DRV_DIR "/usr/local/lib/xorg/modules/drivers/"
 #endif
 
 #ifdef DEBUG_DRI_CALLS
@@ -209,6 +218,85 @@
 
 #define FAKEDRI_JMP64_PATCH_SIZE 13
 
+#if defined(BSD)
+/* Provide basic dladdr1 flags */
+enum {
+	RTLD_DL_SYMENT	= 1
+};
+
+/* Provide a minimal local version of dladdr1 */
+static int
+dladdr1(const void *address, Dl_info *dlip, void **info, int flags)
+{
+	static DRI_ELFSYM desym;
+	GElf_Sym sym;
+	GElf_Shdr shdr;
+	Elf *elf;
+	Elf_Scn *scn;
+	Elf_Data *data;
+	int ret, fd, count, i;
+
+	/* Initialize variables */
+	fd = -1;
+	elf = NULL;
+
+	/* Call dladdr first */
+	ret = dladdr(address, dlip);
+	if (ret == 0) goto err_exit;
+
+	/* Check for supported flags */
+	if (flags != RTLD_DL_SYMENT) return 1;
+
+	/* Open shared library's ELF file */
+	if (elf_version(EV_CURRENT) == EV_NONE) goto err_exit;
+	fd = open(dlip->dli_fname, O_RDONLY);
+	if (fd < 0) goto err_exit;
+	elf = elf_begin(fd, ELF_C_READ, NULL);
+	if (elf == NULL) goto err_exit;
+
+	/* Find the '.dynsym' section */
+	scn = elf_nextscn(elf, NULL);
+	while (scn != NULL) {
+		if (gelf_getshdr(scn, &shdr) == NULL) goto err_exit;
+		if (shdr.sh_type == SHT_DYNSYM) break;
+		scn = elf_nextscn(elf, scn);
+	}
+	if (scn == NULL) goto err_exit;
+
+	/* Search for the requested symbol by name and offset */
+	data = elf_getdata(scn, NULL);
+	count = shdr.sh_size / shdr.sh_entsize;
+	for (i = 0; i < count; i++) {
+		gelf_getsym(data, i, &sym);
+		if ((strcmp(dlip->dli_sname,
+		        elf_strptr(elf, shdr.sh_link, sym.st_name)) == 0) &&
+		    (sym.st_value == (dlip->dli_saddr - dlip->dli_fbase))) {
+			break;
+		}
+	}
+
+	/* Close ELF file */
+	elf_end(elf);
+	close(fd);
+
+	/* Return symbol entry in native format */
+	desym.st_name = sym.st_name;
+	desym.st_info = sym.st_info;
+	desym.st_other = sym.st_other;
+	desym.st_shndx = sym.st_shndx;
+	desym.st_value = sym.st_value;
+	desym.st_size = sym.st_size;
+	*info = &desym;
+	return 1;
+
+	/* Error handler */
+err_exit:
+	if (elf != NULL) elf_end(elf);
+	if (fd >= 0) close(fd);
+	return 0;
+}
+#endif
+
 static void
 vboxPatchMesaExport(const char* psFuncName, const void *pStart, const void *pEnd)
 {