1 /* Loading dynamic objects for GNU Make.
2 Copyright (C) 2012-2013 Free Software Foundation, Inc.
3 This file is part of GNU Make.
5 GNU Make is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3 of the License, or (at your option) any later
10 GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License along with
15 this program. If not, see <http://www.gnu.org/licenses/>. */
27 #define SYMBOL_EXTENSION "_gmk_setup"
35 struct load_list *next;
40 static struct load_list *loaded_syms = NULL;
43 load_object (const gmk_floc *flocp, int noerror,
44 const char *ldname, const char *symname)
46 static void *global_dl = NULL;
51 global_dl = dlopen (NULL, RTLD_NOW|RTLD_GLOBAL);
53 fatal (flocp, _("Failed to open global symbol table: %s"), dlerror ());
56 symp = (load_func_t) dlsym (global_dl, symname);
59 struct load_list *new;
62 /* If the path has no "/", try the current directory first. */
63 if (! strchr (ldname, '/')
65 && ! strchr (ldname, '\\')
68 dlp = dlopen (concat (2, "./", ldname), RTLD_LAZY|RTLD_GLOBAL);
70 /* If we haven't opened it yet, try the default search path. */
72 dlp = dlopen (ldname, RTLD_LAZY|RTLD_GLOBAL);
74 /* Still no? Then fail. */
78 DB (DB_BASIC, ("%s", dlerror ()));
80 error (flocp, "%s", dlerror ());
84 /* Assert that the GPL license symbol is defined. */
85 symp = (load_func_t) dlsym (dlp, "plugin_is_GPL_compatible");
87 fatal (flocp, _("Loaded object %s is not declared to be GPL compatible"),
90 symp = (load_func_t) dlsym (dlp, symname);
92 fatal (flocp, _("Failed to load symbol %s from %s: %s"),
93 symname, ldname, dlerror ());
95 /* Add this symbol to a trivial lookup table. This is not efficient but
96 it's highly unlikely we'll be loading lots of objects, and we only
97 need it to look them up on unload, if we rebuild them. */
98 new = xmalloc (sizeof (struct load_list));
99 new->name = xstrdup (ldname);
101 new->next = loaded_syms;
109 load_file (const gmk_floc *flocp, const char **ldname, int noerror)
111 int nmlen = strlen (*ldname);
112 char *new = alloca (nmlen + CSTRLEN (SYMBOL_EXTENSION) + 1);
113 char *symname = NULL;
119 /* Break the input into an object file name and a symbol name. If no symbol
120 name was provided, compute one from the object file name. */
121 fp = strchr (*ldname, '(');
126 /* There's an open paren, so see if there's a close paren: if so use
127 that as the symbol name. We can't have whitespace: it would have
128 been chopped up before this function is called. */
129 ep = strchr (fp+1, ')');
130 if (ep && ep[1] == '\0')
132 int l = fp - *ldname;;
136 fatal (flocp, _("Empty symbol name for load: %s"), *ldname);
138 /* Make a copy of the ldname part. */
139 memcpy (new, *ldname, l);
143 /* Make a copy of the symbol name part. */
144 symname = new + l + 1;
145 memcpy (symname, fp, ep - fp);
146 symname[ep - fp] = '\0';
150 /* Add this name to the string cache so it can be reused later. */
151 *ldname = strcache_add (*ldname);
153 /* If this object has been loaded, we're done. */
154 loaded = allocated_variable_expand ("$(.LOADED)");
155 fp = strstr (loaded, *ldname);
156 r = fp && (fp==loaded || fp[-1]==' ') && (fp[nmlen]=='\0' || fp[nmlen]==' ');
161 /* If we didn't find a symbol name yet, construct it from the ldname. */
166 fp = strrchr (*ldname, '/');
167 #ifdef HAVE_DOS_PATHS
170 const char *fp2 = strchr (fp, '\\');
176 fp = strrchr (*ldname, '\\');
177 /* The (improbable) case of d:foo. */
178 if (fp && *fp && fp[1] == ':')
185 while (isalnum (*fp) || *fp == '_')
187 strcpy (p, SYMBOL_EXTENSION);
191 DB (DB_VERBOSE, (_("Loading symbol %s from %s\n"), symname, *ldname));
194 symp = load_object (flocp, noerror, *ldname, symname);
198 /* Invoke the symbol. */
201 /* If it succeeded, add the load file to the loaded variable. */
203 do_variable_definition (flocp, ".LOADED", *ldname, o_default, f_append, 0);
209 unload_file (const char *name)
213 for (d = loaded_syms; d != NULL; d = d->next)
214 if (streq (d->name, name) && d->dlp)
216 if (dlclose (d->dlp))
217 perror_with_name ("dlclose", d->name);
226 load_file (const gmk_floc *flocp, const char **ldname, int noerror)
229 fatal (flocp, _("The 'load' operation is not supported on this platform."));
235 unload_file (const char *name)
237 fatal (NILF, "INTERNAL: Cannot unload when load is not supported!");
240 #endif /* MAKE_LOAD */