summaryrefslogtreecommitdiff
path: root/src/backend/port/dynloader/darwin.c
blob: 4c24682e67b0019206cde2b93764a315a5016637 (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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * Dynamic loading support for Darwin
 *
 * If dlopen() is available (Darwin 10.3 and later), we just use it.
 * Otherwise we emulate it with the older, now deprecated, NSLinkModule API.
 *
 * $PostgreSQL: pgsql/src/backend/port/dynloader/darwin.c,v 1.13 2007/11/15 22:25:15 momjian Exp $
 */
#include "postgres.h"

#ifdef HAVE_DLOPEN
#include <dlfcn.h>
#else
#include <mach-o/dyld.h>
#endif

#include "dynloader.h"


#ifdef HAVE_DLOPEN

void *
pg_dlopen(char *filename)
{
	return dlopen(filename, RTLD_NOW | RTLD_GLOBAL);
}

void
pg_dlclose(void *handle)
{
	dlclose(handle);
}

PGFunction
pg_dlsym(void *handle, char *funcname)
{
	/* Do not prepend an underscore: see dlopen(3) */
	return dlsym(handle, funcname);
}

char *
pg_dlerror(void)
{
	return dlerror();
}
#else							/* !HAVE_DLOPEN */

/*
 * These routines were taken from the Apache source, but were made
 * available with a PostgreSQL-compatible license.	Kudos Wilfredo
 * Sánchez <wsanchez@apple.com>.
 */

static NSObjectFileImageReturnCode cofiff_result = NSObjectFileImageFailure;

void *
pg_dlopen(char *filename)
{
	NSObjectFileImage image;

	cofiff_result = NSCreateObjectFileImageFromFile(filename, &image);
	if (cofiff_result != NSObjectFileImageSuccess)
		return NULL;
	return NSLinkModule(image, filename,
						NSLINKMODULE_OPTION_BINDNOW |
						NSLINKMODULE_OPTION_RETURN_ON_ERROR);
}

void
pg_dlclose(void *handle)
{
	NSUnLinkModule(handle, FALSE);
}

PGFunction
pg_dlsym(void *handle, char *funcname)
{
	NSSymbol symbol;
	char	   *symname = (char *) malloc(strlen(funcname) + 2);

	sprintf(symname, "_%s", funcname);
	if (NSIsSymbolNameDefined(symname))
	{
		symbol = NSLookupAndBindSymbol(symname);

		free(symname);
		return (PGFunction) NSAddressOfSymbol(symbol);
	}
	else
	{
		free(symname);
		return NULL;
	}
}

char *
pg_dlerror(void)
{
	NSLinkEditErrors c;
	int			errorNumber;
	const char *fileName;
	const char *errorString = NULL;

	switch (cofiff_result)
	{
		case NSObjectFileImageSuccess:
			/* must have failed in NSLinkModule */
			NSLinkEditError(&c, &errorNumber, &fileName, &errorString);
			if (errorString == NULL || *errorString == '\0')
				errorString = "unknown link-edit failure";
			break;
		case NSObjectFileImageFailure:
			errorString = "failed to open object file";
			break;
		case NSObjectFileImageInappropriateFile:
			errorString = "inappropriate object file";
			break;
		case NSObjectFileImageArch:
			errorString = "object file is for wrong architecture";
			break;
		case NSObjectFileImageFormat:
			errorString = "object file has wrong format";
			break;
		case NSObjectFileImageAccess:
			errorString = "insufficient permissions for object file";
			break;
		default:
			errorString = "unknown failure to open object file";
			break;
	}

	return (char *) errorString;
}

#endif   /* HAVE_DLOPEN */